阅读《深入浅出Webpack》和官方文档 -- 基础

基础

  1. 模块化

CommonJS: 用于Node.js环境

// 导出
module.exports = moduleA.func;
// 导入
const moduleA = require( url );

AMD: 用于Node.js环境,浏览器。异步方式家在模块 -> requirejs

// 定义模块
define( 'module', ['dep'], function(dep) {
  return exports;
} )
// 导入模块
require( ['module'], function(module) {} )

ES6模块化: 需要转化成es5运行

// 导出
export function  hello(){};
export default {};
// 导入
import { A } from url;
import B from url;

一直计划说详细学一下webpack,然后由于各种因素拖到了现在。 结合《深入浅出Webpack》和官方文档。

概念: 静态模块打包器(module bundler), 将从入口开始 构建整个应用的依赖关系图,然后将所有模块打包成一个或者多个bundle。

  • 入口(entry): 应用从哪个文件作为依赖图的开始。
  • 出口(output): 在哪里输出根据依赖图所创建的bundles, 以及如何命名这些文件。【默认为./dist】
  • 插件(plugins): loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。
  • 模式(mode): 可以启用响应模式下的webpack内置的优化(development, production)
  • Chunk: 一个chunk由多个模块组成, 用于代码合并与分割。
  • module: 处理模块的规则
  • resolve:寻找模块的规则

1. Entry: 可配置 多页面应用 或者 多入口的单页应用

const config = {
  entry: './path/to/my/entry/file.js'   // string 类型
};
const config = {
  entry: ['./path/to/my/entry/file1.js', './path/to/my/entry/file2.js']   // array 类型  
  // 数组里的最后一个入口文件的模块会被导出。
};
const config = {
  entry: {  // object 类型
      pc:  './pc/pc.js',
      h5:  './h5/h5.js',
  } 
};

2. Output:

 const config = {
  output: {
    filename: "",  // string 类型
    chunkFilename: "", // string  需要在runtime根据chunk发送的请求去生成
    path: path.resolve(__dirname, 'dist/assets'),
    publicPath: "", // 静态资源的路径。 需要按照开发环境或者生产环境配置
    library:"", // string 导出库的名称
    libraryTarget: "",  // enum  已何种方式导出库
    libraryExport: "", // string, array 导出那些子模块
  }
};

内置变量列表:

  1. id: Chunk的唯一标识, 从0开始
  2. name: Chunk的名称
  3. hash:Chunk的唯一标识的Hash值
  4. chunkhash: Chunk内容的Hash值
  5. query 模块文件名 ? 后面的字符串
    注: Hash的长度是可以指定的如:[hash:8] ,默认20
    其他配置项 在官方文档中有介绍或者后续的笔记中更新。

3. Module: 如何处理不同类型的模块

 const config = {
  module: {
    noParse: /jquery/ ,  // 忽略部分文件的解析和处理( 被忽略的文件不该包含import, require, define)
    rules: [  // 配置Loader
      {
        test: /\.css/,   //  正则表达式的匹配规则, 也可是个array
        use: [],  // 数组中可以是string, object
        enforce: "pre", // enum  ["pre", "post"] 
        include: path.resolve(__dirname, 'src'),// 仅匹配src目录中的文件
        exclude: path.resolve(__dirname, 'dist'),// 排除dist目录中的文件
        and: [],  // 必须匹配所有条件
        or: [],
        not: [],
      }
    ],
    parser: {  // 指定解析器的开关, 精确控制哪些语法可以被解析
       amd: false,
       commonjs: true,
    }   
  }
};

其中当use中,设置为对象时, 可以向其loader传入多个参数

  use: [
    {
      loader: "",  //  所使用的loader
      options: {},  // 向loader传入的参数
    }
  ]

使用oneOf,对匹配规则进行嵌套,

    rules: [  // 配置Loader
      {
        test:  /\.css/,
        oneOf: [ // 可以指定嵌套规则
          {
            resourceQuery: /inline/, // foo.css?inline
            use: 'url-loader'
          },
          {
            resourceQuery: /external/, // foo.css?external
            use: 'file-loader'
          }
        ], 
      }
    ]

配置loader 通过一下方式完成:

  1. 条件匹配: 通过test,include,exclude
  2. 应用规则: 通过use应用loader
  3. 重置顺序: 默认loader的顺序是从右向左的, 使用enforce选项将loader的执行顺序改变

webpack自带的loader库

4. Resolve: 模块如何被解析, (webpack本身含有默认值)

const config = {
  resolve: {
    alias: { // 创建别名。 使引用是更方便,避免过多的相对路径
      images: path.resolve(__dirname, 'src/images/')
      css$: path.resolve(__dirname, 'src/assets/css')  // $ 标识精准匹配
    },
    extensions: [".js",".json"], // 当无后缀名时,默认自动带上后缀解析
    mainFiles: [], // 指定导入模块时 导入的哪部分代码
    modules: ["node_modules"], // 默认只去node_modules中寻找第三方模块
    enforceExtension: false, // 允许无扩展名文件的引用
    unsafeCache: /\aa/, // 开启仅缓存aa模块  regex, array, boolean
    plugins: [],  // 额外的解析插件列表
  }
}

mainFiles, 默认为["browser", "module", "main"], 默认顺序
在其他target时, 默认为["module","main"]
即 对应 所引用包的package.json中的

{
  main: "build/d3.Node.js",
  browser: "build/d3.js",
  module: "index",
}

5. Plugins

const config = {
 plugins: [ // array
     // 每项是一个插件的实例, 将参数通过构造函数传入
     new CommonsChunkPlugin({  // 将所有公共代码提取到common代码块中
       name: "common",
       chunks: ["a","b"]
     })
 ]
}

Webpack自带的插件库

6. DevServer: 在开发中的行为

const config = {
 devServer: {
   host: "", // 默认为localhost, 设置为ip 供外部访问
   port: "", // 监听的端口, 默认8080
   inline: true,  // false 时 责启用iframe模式, true为嵌入bundle中
   allowedHosts: [], // 设置白名单
   compress: true, //  启用gzip压缩
   contentBase: path.join(__dirname, "public"), // 从哪提取静态文件, 默认当前执行的目录 ./
   disableHostCheck: false,  // 关闭host检查,使其他设备也能访问本地服务
   lazy: true, // 开启惰性模式,仅在请求时编译,即不监听文件改动
   filename: "", // 只在请求该文件时编译, 必须开启惰性模式
   headers: {},  // 在所有想用中添加首部内容
   hot: true, // 开启模块热替换,仅刷新改变的模块
   clientLogLevel: "info",  // enum 客户端的日志级别,默认info
   https: true, // 默认使用http服务,开启https 后自动生成一份证书,也可用{}配置自己的证书,读文件
   open: true,  // 第一次构建后 自动打开浏览器
   proxy: {
     "/api":  "http://localhost:3000",
     "/users": {
       target: "https://localhost:3000",
       pathRewrite: {"^/users" : ""},  // 将路径重写 如 /users/login -> /login
       secure: false, // 若代理到https服务,则需要将secure设为false
       bypass: function(req, res, proxyOptions) {
         if (req.headers.accept.indexOf("html") !== -1) {
           console.log("Skipping proxy for browser request.");
           return "/index.html";
         }
       }
     }
   },
   quiet:  true, // 除初始启动信息外都不会打印到控制台
 }
}
  proxy: [{  // 针对多个请求 进行代理
    context: ["/auth", "/api"],
    target: "http://localhost:3000",
  }]

7. Devtool:配置source map

const config = {
  devtool: "none" // 构建source-map方便调试  enum 
}

具体的选项和构建速度 在官方文档中有详细的表格

8. Target:配置source map

const config = {
  target: "web",  // enum 默认web, 还有node,webworker, electron等  
const webpack = require("webpack");

const options = {
  target: (compiler) => {  // function  使用非自带的target的插件
    compiler.apply(
      new webpack.JsonpTemplatePlugin(options.output),
      new webpack.LoaderTargetPlugin("web")
    );
  }
};

9. Watch: 监听规则

const config = {
  watch: true, //  默认false, 在devServer中默认开启
  watchOptions: {
    ignored: /node_modules/,  // 或者使用"files/**/*.js" 这种形式
    poll: 1000, // number, boolean 每秒进行轮询
    aggregateTimeout: 300, // 监听到变化后 延迟300ms再执行
  }
}

10. Externals不打包某些模块

const config = {
  externals: {
    jquery: 'jQuery'  //  string, array. object, function, regex
  }
}

因为全局引入了一些模块或变量,然后import的时候,会使webpack将模块再打包一次,所以会出现重复的内容,使用externals排除在外。

11. Performance

const config = {
  performance: {
    hints: "warning",  //  打开提示,在开发环境使用warning,生产error
    maxEntrypointSize: 400000, //  根据入口起点的最大体积,控制 webpack 何时生成性能提示  默认值 250000 bytes
    maxAssetSize: 100000, // 根据单个资源体积,控制 webpack 何时生成性能提示
    assetFilter: function(assetFilename) {  // 只给出 .js 文件的性能提示。
      return assetFilename.endsWith('.js');
    }
  }
}

12. Stats

stats: "minimal", // string  enum  只在发生错误或有新的编译时输出
stats: {}, // 使用对象对统计信息 进行更精确的控制

至此 ,文档中的概念,配置,Loaders, plugins 已完成概览。接下来抽空完成,实战, 优化, 原理。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容