通过不断的调整和测试,关于 react 的 webpack 配置终于新鲜出炉。本次的重点主要集中在开发环境上,生产环境则是使用 webpack 的 production 默认模式。css
本次配置主要有:node
eslint+prettier;react
optimization.splitChunks;webpack
happypack;es6
DllReferencePlugin & DllPlugin;web
...npm
讲真,对于初次接触 webpack 的同窗,怕的可能不是 webpack 的配置,而是长长的 package.json。依赖那么多,你怎么就知道须要哪些依赖呢。不开玩笑,我还真知道。 webpack 的依赖主要是一些 loader 和 plugins。咱们知道单页面引用被打包后,原有的结构基本上不复存在了。而以前引用的图片或字体资源还按照以前的路径查找,确定是找不到的。那么咱们就须要转换工具(顺便转换资源)—— url-loader
|file-loader
。 大多数人写样式时,喜欢使用 css、less、sass。这时也会有对应的工具 style-loader
, css-loader
, less-loader
。 想要使用 JavaScript 新特性或处理兼容性,就用 babel-loader
。以上这些基本上能够应付一些简单的项目。可实际上呢?json
我信你个鬼,你这个糟老头坏的很!浏览器
看文档啊,看官方介绍啊。本次也是经过看 babel 文档,和一些依赖文档来配置 webpack 的,全程无压力,并且很正宗。因此,文档很重要。缓存
若是时团队合做,代码规范是很重要的。能够经过 eslint+prettier 规范。这两个工具各有侧重点,不过官网也提供了二者结合的方案。详细介绍见官网。我我的不习惯建立太多的配置文件,因此都放在了 package.json 文件中。
// webpack.common.js
{
enforce: "pre",
test: /\.m?jsx?$/,
exclude: /node_modules/,
loader: "eslint-loader",
options: {
fix: true,
cache: true,
formatter: require("eslint-friendly-formatter"),
}
},
复制代码
"eslintConfig": {
"parser": "babel-eslint",
"env": {
"browser": true,
"es6": true,
"node": true
},
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"extends": [
"plugin:prettier/recommended"
]
},
"prettier": {
"singleQuote": true,
"semi": true
},
复制代码
开发环境没什么好说的了,简单易配置,官网很详细。
// webpack.dev.js
plugins: {
//...
new webpack.HotModuleReplacementPlugin()
},
devtool: "eval-source-map",
devServer: {
contentBase: path.resolve(__dirname, '..', 'dist'),
port: APP_CONFIG.port,
hot: true,
open: true
}
// index.js
// 入口处要配置这些,别忘了。
// 由于有冒泡的机制,因此在顶端加一个就好。
if (module.hot) {
module.hot.accept('./views/login/index.js', () => {
render(App) // 渲染应用
})
}
复制代码
这个配置是用来分割包的。在性能优化上,请求数和请求包的大小也是很重要的优化点。请求数量和请求数据大小要控制在合理的范围内。 不过一般状况下,咱们会将包分割为内容不变的部分和内容变化的部分。这不单单是为了将大的包分割成更小的包,也是为了可以充分利用缓存机制。
// webpack.common.js
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
verdor: {
test: /[\\/]node_modules[\\/]/,
name: 'verdors',
chunks: 'all',
priority: -10,
},
common: {
name: 'common',
chunks: 'all',
minChunks: 2,
priority: -20,
}
}
}
复制代码
转换文件算是打包过程当中比较耗时的事情,经过 happypack 能够将这件事分摊给多个 node 进程,这样就会大大缩短了打包时间(同理,能够考虑使用 thread-loader
)。不过进程之间的通讯是要开销的,这是一个优化方向,要不要采用,还须要酌情考虑。
// loader
{
test: /\.m?jsx?$/,
exclude: /node_modules/,
use: 'happypack/loader?id=js',
}
// plugins
new HappyPack({
id: 'js',
threadPool: happyThreadPool,
loaders: [{
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: [['@babel/preset-env', {
"useBuiltIns": "usage",
"corejs": 3
}], "@babel/preset-react"],
plugins: ['@babel/transform-runtime',
"@babel/plugin-proposal-class-properties", [
"import",
{
"libraryName": "antd",
"style": true
}
]
]
}
}]
})
复制代码
不喜欢单独的 babel 文件,因此 babel 的配置都在这里了。其实,关于 babel 要配置的内容仍是挺多的。不过不要怕,babel 的官方文档有详细说明。
以前也提到过,一般咱们会使用 optimization.splitChunks
来处理第三方库,将其分割成不变的部分。但是,每次打包的时候都须要重复这一步骤。 这时候咱们就想啊,不变的部分打包一次不就能够了么,以后就只打包那些常常变化的部分,这样不就能提升效率了么?是的, DllReferencePlugin & DllPlugin
基本上要作的就是这么一回事。因此,咱们会针对这两部分作不一样的配置。
// webpack.dll.js
new webpack.DllPlugin({
context: process.cwd(),
path: path.join(__dirname, '..', 'dist', 'dll', '[name]-manifest.json'),
name: '[name]_[hash]'
})
// webpack.common.js
new webpack.DllReferencePlugin({
context: process.cwd(),
manifest: require(path.resolve(__dirname, '..', 'dist', 'dll', "vendor-manifest.json"))
}),
复制代码
multi-spa-webpack-cli
已经发布到 npm,只要在 node 环境下安装便可。一路按 Enter,所有源码都在里面!!!
npm install multi-spa-webpack-cli -g
复制代码
使用步骤以下:
# 1. 初始化项目
multi-spa-webpack-cli init spa-project
# 2. 进入文件目录
cd spa-project
# 3. 安装依赖
npm install
# 4. 打包不变的部分
npm run build:dll
# 5. 启动项目(手动打开浏览器:localhost:8090)
npm start
复制代码
webpack 系列: