前言:承接之前的webpack学习,请看完入门笔记1后再看本章内容
第 7 章:Webpack 配置详情
7.1 entry
entry: 入口起点
- string --> './src/index.js',单入口
打包形成一个 chunk。 输出一个 bundle 文件。此时 chunk 的名称默认是 main - array --> ['./src/index.js', './src/add.js'],多入口
所有入口文件最终只会形成一个 chunk,输出出去只有一个 bundle 文件。
(一般只用在 HMR 功能中让 html 热更新生效) - object,多入口
有几个入口文件就形成几个 chunk,输出几个 bundle 文件,此时 chunk 的名称是 key 值
--> 特殊用法:
1 entry: { 2 // 最终只会形成一个chunk, 输出出去只有一个bundle文件。 3 index: ['./src/index.js', './src/count.js'], 4 // 形成一个chunk,输出一个bundle文件。 5 add: './src/add.js' 6 }
7.2 output
1 output: { 2 // 文件名称(指定名称+目录) 3 filename: 'js/[name].js', 4 // 输出文件目录(将来所有资源输出的公共目录) 5 path: resolve(__dirname, 'build'), 6 // 所有资源引入公共路径前缀 --> 'imgs/a.jpg' --> '/imgs/a.jpg' 7 publicPath: '/', 8 chunkFilename: 'js/[name]_chunk.js', // 指定非入口chunk的名称 9 library: '[name]', // 打包整个库后向外暴露的变量名 10 libraryTarget: 'window' // 变量名添加到哪个上 browser:window 11 // libraryTarget: 'global' // node:global 12 // libraryTarget: 'commonjs' // conmmonjs模块 exports 13 },
7.3 module
1 module: { 2 rules: [ 3 // loader的配置 4 { 5 test: /.css$/, 6 // 多个loader用use 7 use: ['style-loader', 'css-loader'] 8 }, 9 { 10 test: /.js$/, 11 // 排除node_modules下的js文件 12 exclude: /node_modules/, 13 // 只检查src下的js文件 14 include: resolve(__dirname, 'src'), 15 enforce: 'pre', // 优先执行 16 // enforce: 'post', // 延后执行 17 // 单个loader用loader 18 loader: 'eslint-loader', 19 options: {} // 指定配置选项 20 }, 21 { 22 // 以下配置只会生效一个 23 oneOf: [] 24 } 25 ] 26 },
7.4 resolve
1 // 解析模块的规则 2 resolve: { 3 // 配置解析模块路径别名: 优点:当目录层级很复杂时,简写路径;缺点:路径不会提示 4 alias: { 5 $css: resolve(__dirname, 'src/css') 6 }, 7 // 配置省略文件路径的后缀名(引入时就可以不写文件后缀名了) 8 extensions: ['.js', '.json', '.jsx', '.css'], 9 // 告诉 webpack 解析模块应该去找哪个目录 10 modules: [resolve(__dirname, '../../node_modules'), 'node_modules'] 11 }
这样配置后,引入文件就可以这样简写:import '$css/index';
7.5 dev server
1 devServer: { 2 // 运行代码所在的目录 3 contentBase: resolve(__dirname, 'build'), 4 // 监视contentBase目录下的所有文件,一旦文件变化就会reload 5 watchContentBase: true, 6 watchOptions: { 7 // 忽略文件 8 ignored: /node_modules/ 9 }, 10 // 启动gzip压缩 11 compress: true, 12 // 端口号 13 port: 5000, 14 // 域名 15 host: 'localhost', 16 // 自动打开浏览器 17 open: true, 18 // 开启HMR功能 19 hot: true, 20 // 不要显示启动服务器日志信息 21 clientLogLevel: 'none', 22 // 除了一些基本信息外,其他内容都不要显示 23 quiet: true, 24 // 如果出错了,不要全屏提示 25 overlay: false, 26 // 服务器代理,--> 解决开发环境跨域问题 27 proxy: { 28 // 一旦devServer(5000)服务器接收到/api/xxx的请求,就会把请求转发到另外一个服务器3000 29 '/api': { 30 target: 'http://localhost:3000', 31 // 发送请求时,请求路径重写:将/api/xxx --> /xxx (去掉/api) 32 pathRewrite: { 33 '^/api': '' 34 } 35 } 36 } 37 }
其中,跨域问题:同源策略中不同的协议、端口号、域名就会产生跨域。
正常的浏览器和服务器之间有跨域,但是服务器之间没有跨域。代码通过代理服务器运行,所以浏览器和代理服务器之间没有跨域,浏览器把请求发送到代理服务器上,代理服务器替你转发到另外一个服务器上,服务器之间没有跨域,所以请求成功。代理服务器再把接收到的响应响应给浏览器。这样就解决开发环境下的跨域问题。
7.6 optimization
contenthash 缓存会导致一个问题:修改 a 文件导致 b 文件 contenthash 变化。
因为在 index.js 中引入 a.js,打包后 index.js 中记录了 a.js 的 hash 值,而 a.js 改变,其重新打包后的 hash 改变,导致 index.js 文件内容中记录的 a.js 的 hash 也改变,从而重新打包后 index.js 的 hash 值也会变,这样就会使缓存失效。(改变的是a.js文件但是 index.js 文件的 hash 值也改变了)
解决办法:runtimeChunk --> 将当前模块记录其他模块的 hash 单独打包为一个文件 runtime,这样 a.js 的 hash 改变只会影响 runtime 文件,不会影响到 index.js 文件
1 output: { 2 filename: 'js/[name].[contenthash:10].js', 3 path: resolve(__dirname, 'build'), 4 chunkFilename: 'js/[name].[contenthash:10]_chunk.js' // 指定非入口文件的其他chunk的名字加_chunk 5 }, 6 optimization: { 7 splitChunks: { 8 chunks: 'all', 9 /* 以下都是splitChunks默认配置,可以不写 10 miniSize: 30 * 1024, // 分割的chunk最小为30kb(大于30kb的才分割) 11 maxSize: 0, // 最大没有限制 12 minChunks: 1, // 要提取的chunk最少被引用1次 13 maxAsyncRequests: 5, // 按需加载时并行加载的文件的最大数量为5 14 maxInitialRequests: 3, // 入口js文件最大并行请求数量 15 automaticNameDelimiter: '~', // 名称连接符 16 name: true, // 可以使用命名规则 17 cacheGroups: { // 分割chunk的组 18 vendors: { 19 // node_modules中的文件会被打包到vendors组的chunk中,--> vendors~xxx.js 20 // 满足上面的公共规则,大小超过30kb、至少被引用一次 21 test: /[\/]node_modules[\/]/, 22 // 优先级 23 priority: -10 24 }, 25 default: { 26 // 要提取的chunk最少被引用2次 27 minChunks: 2, 28 prority: -20, 29 // 如果当前要打包的模块和之前已经被提取的模块是同一个,就会复用,而不是重新打包 30 reuseExistingChunk: true 31 } 32 } */ 33 }, 34 // 将index.js记录的a.js的hash值单独打包到runtime文件中 35 runtimeChunk: { 36 name: entrypoint => `runtime-${entrypoint.name}` 37 }, 38 minimizer: [ 39 // 配置生产环境的压缩方案:js/css 40 new TerserWebpackPlugin({ 41 // 开启缓存 42 cache: true, 43 // 开启多进程打包 44 parallel: true, 45 // 启用sourceMap(否则会被压缩掉) 46 sourceMap: true 47 }) 48 ] 49 }
第 8 章:webpack5
此版本重点关注以下内容:
- 通过持久缓存提高构建性能.
- 使用更好的算法和默认值来改善长期缓存.
- 通过更好的树摇和代码生成来改善捆绑包大小.
- 清除处于怪异状态的内部结构,同时在 v4 中实现功能而不引入任何重大更改.
- 通过引入重大更改来为将来的功能做准备,以使我们能够尽可能长时间地使用 v5.
1.下载
- npm i webpack@next webpack-cli -D
2.自动删除 Node.js Polyfills
早期,webpack 的目标是允许在浏览器中运行大多数 node.js 模块,但是模块格局发生了变化,许多模块用途现在主要是为前端目的而编写的。webpack <= 4 附带了许多 node.js 核心模块的 polyfill,一旦模块使用任何核心模块(即 crypto 模块),这些模块就会自动应用。
尽管这使使用为 node.js 编写的模块变得容易,但它会将这些巨大的 polyfill 添加到包中。在许多情况下,这些 polyfill 是不必要的。webpack 5 会自动停止填充这些核心模块,并专注于与前端兼容的模块。
迁移:
- 尽可能尝试使用与前端兼容的模块。
- 可以为 node.js 核心模块手动添加一个 polyfill。错误消息将提示如何实现该目标。
3.Chunk 和模块 ID
添加了用于长期缓存的新算法。在生产模式下默认情况下启用这些功能。
chunkIds: "deterministic", moduleIds: "deterministic"
Chunk ID
你可以不用使用 import(/* webpackChunkName: "name" */ "module")
在开发环境来为 chunk 命名,生产环境还是有必要的
webpack 内部有 chunk 命名规则,不再是以 id(0, 1, 2)命名了
4.Tree Shaking
- webpack 现在能够处理对嵌套模块的 tree shaking
1 // inner.js 2 export const a = 1; 3 export const b = 2; 4 5 // module.js 6 import * as inner from './inner'; 7 export { inner }; 8 9 // user.js 10 import * as module from './module'; 11 console.log(module.inner.a);
在生产环境中, inner 模块暴露的 b
会被删除
- webpack 现在能跟多个模块之前的关系
1 import { something } from './something'; 2 3 function usingSomething() { 4 return something; 5 } 6 7 export function test() { 8 return usingSomething(); 9 }
当设置了"sideEffects": false
时,一旦发现test
方法没有使用,不但删除test
,还会删除"./something"
- webpack 现在能处理对 Commonjs 的 tree shaking
5.Output
webpack 4 默认只能输出 ES5 代码
webpack 5 开始新增一个属性 output.ecmaVersion, 可以生成 ES5 和 ES6 / ES2015 代码.
如:output.ecmaVersion: 2015
6.SplitChunk
1 // webpack4 2 minSize: 30000; 3 4 5 // webpack5 6 minSize: { 7 javascript: 30000, 8 style: 50000, 9 }
7.Caching
1 // 配置缓存 2 cache: { 3 // 磁盘存储 4 type: "filesystem", 5 buildDependencies: { 6 // 当配置修改时,缓存失效 7 config: [__filename] 8 } 9 }
缓存将存储到 node_modules/.cache/webpack
8.监视输出文件
之前 webpack 总是在第一次构建时输出全部文件,但是监视重新构建时会只更新修改的文件。
此次更新在第一次构建时会找到输出文件看是否有变化,从而决定要不要输出全部文件。
9.默认值
entry: "./src/index.js
output.path: path.resolve(__dirname, "dist")
output.filename: "[name].js"
其他
webpack官网:https://www.webpackjs.com/concepts/
其他优秀的webpack推荐:Webpack4不求人系列(共5篇)