打包文件资源问题
filename 指列在 entry 中,打包后输出的文件的名称。
chunkFilename 指未列在 entry 中,却又需要被打包出来的文件的名称。
项目缓存问题
当项目上线新版本的时候,用户浏览器可能仍然使用的是之前 html 和 js 文件的缓存。通过以下几个方法可以解决这个问题。
- 文件命名使用哈希值,这样当发布新版本就会请求新版本的资源文件。vue-cli 中默认有这个功能,webpack 在每次构建的时候都会生成 hash,contenthash,chunkhash 三个哈希值
- hash 这是工程级别的,即每次修改任何一个文件,所有文件名的 hash 至都将改变。所以一旦修改了任何一个文件,整个项目的文件缓存都将失效。
- chunkhash 根据不同的入口文件(Entry)进行依赖文件解析、构建对应的 chunk,生成对应的哈希值。在生产环境里把一些公共库和程序入口文件区分开,单独打包构建,接着我们采用 chunkhash 的方式生成哈希值,那么只要我们不改动公共库的代码,就可以保证其哈希值不会受影响。并且 webpack4 中支持了异步 import 功能,chunkhash 也作用于此。
- contenthash 一般来说,样式是作为模块 import 到 js 文件中,他们的 chunkhash 是一致的,这导致只要对应的 css 或者 js 改变,chunkhash 就会改变。而 contenthash 是针对文件内容级别的,只有自身模块的内容变了,hash 值才改变
- html 加上
1 | <meta |
- 配置 nginx,禁止 html 入口文件的缓存
1 | location = /index.html { |
- 使用 HtmlWebpackPlugin 插件,一个典型的配置如下
1 | new HtmlWebpackPlugin({ |
图中最右边一列就是资源的 chunkname
MiniCssExtractPlugin
之前项目使用的是 ExtractTextPlugin 对 css 进行抽出并打包,然而 ExtractTextPlugin 在 4.0 版本后不再支持对 css 进行打包 (会在生成的 css 文件末尾附加 webpack 运行时的代码),后学习得知现在应使用 MiniCssExtractPlugin 对 css 进行抽离
CleanWebpackPlugin
这个插件的作用是每次构建的时候,清理重复构建的文件,因为使用哈希方式构建的时候,文件名不同,更改的文件不会直接替换。个人感觉使用 rm -rf dist/* 清理也可以 当然这可以避免你神志不清时误把整个项目文件删了
1 | new CleanWebpackPlugin(["dist"]); |
optimization.splitChunks
非常实用的功能,抽出代码中的公共组件到独立的文件,举个例子
1 | cacheGroups: { |
如果没有 name 属性,a 入口文件引用了 vue 和 axios, b 入口文件引用了 react 和 axios,那么 webpack 就会把 axios 单独抽离出来为独立的 chunk,同时 vue 和 react 在各自的独立 chunk 中
而如果有 name 属性,那么所有依赖文件都会打包到命名的 chunk 文件中,这个原理同样适用于 CSS 的打包。
1 | optimization: { |
可以将 node_modules 中代码单独打包一个 chunk 最终输出
通过 js 代码让文件打包成单独 chunk
1 | import(/*webpackChunkName:'test',webpackPrefetc:true*/,"./test") |
懒加载 当文件需要时才加载
预加载 prefetch 会在使用之前,提前加载 js 文件,等其他资源加载完毕了,再偷偷加载
正常加载认为是并行加载
OptimizeCssAssetsPlugin
我在打包时发现 node_modules 中的 css 文件无法被压缩。css loader 中的 minimize 选项早已被废弃,尝试使用了这个插件后解决了问题。
devserver
- proxy
代理的只能是本地 如果本身请求的目的地址已经指定不是本地,那么这个请求不会被 webpack 代理 - HMR
- 样式文件 可以使用 因为 style-loader 内部实现了 HMR
- js 文件 默认不能使用 HMR 功能
- html 文件不能热更新 将 html 文件 加入 entry 这样会重新加载页面 不需要作 HMR 功能
sourcemap
类型 | 描述 |
---|---|
source-map | 外部 错误代码的准确信息访问到源代码的准确位置 |
inline-source-map | 内联 只生成一个 sourcemap |
hidden-source-map | 外联 错误代码错误原因,但是没有错误位置,不能追踪源代码错误,只能提示到构建后代码的错误位置 |
eval-source-map | 内联 每一个文件都生成对应的 source-map,都在 eval 错误代码准确信息,和源代码的错误位置 |
nosources-source-map | 外部 错误代码准确信息,但是没有任何源代码信息 |
cheap-source-map | 外部 错误代码准确信息和源代码的错误位置 只能精确到行 |
cheap-module-source-map | 外部 错误代码准确信息 和 源代码错误位置 |
module 会将 loader 的 source map 加入
开发环境:速度快,调试更友好
速度快(eval>inline>cheap)
eval-cheap-source-map
eval-source-map
调试更友好
source-map
cheap-moudule-source-map
cheap-source-map
eval-cheap-source-map
- 内联和外部的区别 1. 外部生成了文件,内联没有 2. 内联构建速度更快
开发环境:速度快,调试更友好
eval>inline>cheap
source-map
cheap-module-source-map
cheap-source-map
eval-source-map / eval-cheap-moudule-source-map
生产环境:源代码要不要隐藏?调试友好程度
内联会让代码变大,所以再生产环境不用内联
nosources-source-map 全部隐藏
hidden-source-map 只隐藏代码,会提示构建代码错误信息
babel-loader
babel 缓存 cacheDirectory: true
tree shakin 去除无用代码
必须使用 ES6 模块化
开启 production 环境
在 package.json 中配置 “sideEffects”:false 所有的代码都没有副作用,都可以进行 tree shaking 可能会把 css/ @bable/polyfill 文件干掉
- 定义 nodejs 环境变量:决定使用 browserslist 的哪个环境 process.env.NODE_ENV = ‘production’
PWA
workbox->workbox-webpack-plugin
1 | new WorkboxWebpackPlugin.GenerateSW { |
eslint 不认识 window,navigator 全局变量,需要修改
1 | env: { |
多进程打包 thread-loader
开启多进程打包,进程启动大概 600ms,进程通信也有开销
多用在 babel-loader
1 | { |
externals 忽略打包
1 | externals: { |
dll
打包 dll
1 | const { resolve } = require("path"); |
定义 dll
1 | new webpack.DLLReferencePlugin({ |
引用 dll
1 | new AddAssetHtmlWebpackPlugin({ |
配置详解
module
- enforce:’pre’, // 优先执行
- enforce:’post’, // 延后执行
resolve 解析模块的规则
- alias 配置解析模块的别名
- extensions:[‘.js’,’json’] 配置省略文件路径的后缀名
- modules:[resolve(__dirname,’../../node_modules’),’node_modules’] 解析模块去找哪个目录
optimization
1 | optimization: { |