【webpack系列】从零搭建 webpack4+react 脚手架(二)
在上一节我们已经搭建了一个最基本的webpack环境, 这一节我们带着上节的一些疑问,继续优化我们的react工程。
?
1.整合html-webpack-plugin
?
public的index.html应该自动编译到dist目录,并且所有的js引用是自动添加的。你可以使用html-webpack-plugin插件来处理这个优化。
(1)安装html-webpack-plugin:npm install --save-dev html-webpack-plugin (2)在webpack.prod.conf.js中配置plugins属性。const merge = require(‘webpack-merge‘); const baseWebpackConfig = require(‘./webpack.base.conf.js‘); const HtmlWebpackPlugin = require(‘html-webpack-plugin‘); module.exports = merge(baseWebpackConfig,{ mode: ‘production‘,plugins: [ new HtmlWebpackPlugin({ template: ‘public/index.html‘,inject: ‘body‘,minify: { removeComments: true,collapseWhitespace: true,removeAttributeQuotes: true },}) ] }); (3)删除index.html中手动引入的script标签index.html的代码应该是这样的: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>从零开始搭建react工程</title> </head> <body> <div id="root"></div> </body> </html> (4)重新执行编译npm run build 查看dist文件夹,index.html也被加载进来了,并且已经自动加上了script标签。 ?
2.为导出的js文件添加内容hash
?
当我们的业务有修改,bundle被重新打包,很可能在客户的电脑上并没有奏效,你告诉客户,应该是被缓存了,需要刷新浏览器,清理下浏览器缓存。这也许能解决问题,但是太糟糕了,我们有更好的方式,让导出的js文件加上文件hash,从而每次修改,转译出的js文件名称都不相同,那么js文件当然不会被缓存了。
添加文件hash的方法很简单,只要修改 output.filename 属性即可,这里我们做一个小小的优化,把导出的文件存放在js目录下,并且直接使用name+chunkhash的方式来命名。 filename: "js/[name].[chunkhash:16].js" 其中,name就是模块名称,我们在entry中进行过配置,chunkhash是文件内容的hash,webpack默认采用md5的方式对文件进行hash。16是hash的长度,如果不设置,webpack会设置默认值为20。 现在,你的webpack.prod.conf.js文件看起来应该是这样: const merge = require(‘webpack-merge‘); const baseWebpackConfig = require(‘./webpack.base.conf.js‘); const HtmlWebpackPlugin = require(‘html-webpack-plugin‘); module.exports = merge(baseWebpackConfig,output: { filename: "js/[name].[chunkhash:16].js",},}) ] }); ?
3.编译前清理dist目录
?
现在,如果你修改了你的业务代码,然后重新编译,你会发现在dist/js文件夹出现多个js文件。因为导出的js文件hash已经不相同,每次编译都会增加新的js文件,原来的文件没有被删除。所以,我们需要在编译前进行清理dist文件夹。
(1)安装clean-webpack-pluginnpm install --save-dev clean-webpack-plugin (2)修改webpack.prod.conf.js,使用clean-webpack-pluginconst merge = require(‘webpack-merge‘); const baseWebpackConfig = require(‘./webpack.base.js‘); const HtmlWebpackPlugin = require(‘html-webpack-plugin‘); const CleanWebpackPlugin = require(‘clean-webpack-plugin‘); module.exports = merge(baseWebpackConfig,}),new CleanWebpackPlugin([‘../dist‘],{ allowExternal: true }) ] }); (3)执行试试看npm run build 编译过程,注意查看控制台输出,你会发现webpack删除了dist目录。 ?
4.非业务代码单独打包
?
在build结束,webpack会在终端显示打包文件的大小,我们可以看到这个app.js包大概在96.9KB
? 随着我们业务代码的增加,这个包将会越来越大。 entry: { app: ‘./app/index.js‘,framework:[‘react‘,‘react-dom‘], 重新执行npm run build,再看看。 的确,react和react-dom 被编译成framework.js。可是,你会发现,app.js并没有减少,还是96.9KB。因为我们还缺少一步,就是抽离app.js中公共的代码。 optimization: { splitChunks: { chunks: "all",minChunks: 1,minSize: 0,cacheGroups: { framework: { test: "framework",name: "framework",enforce: true } } } } cacheGroups对象,定义了需要被抽离的模块,其中test属性是比较关键的一个值,他可以是一个字符串,也可以是正则表达式,还可以是函数。如果定义的是字符串,会匹配入口模块名称,会从其他模块中把包含这个模块的抽离出来。name是抽离后生成的名字,和入口文件模块名称相同,这样抽离出来的新生成的framework模块会覆盖被抽离的framework模块,虽然他们都叫framework。 注意查看生成的文件的hash,接下去我们随意修改app/index.js的代码。重新执行npm run build编译。看看编译后的结果: 看到了吗,app的hash发生了改变(它不能被浏览器缓存),而framework没有改变(它会被浏览器缓存),这达到了我们预期的结果。
5.压缩js文件
?
打开build后的js文件看看,js文件没有被压缩。在prod环境,我们希望js已经被压缩了,这样做的好处是减少文件体积,更快地被用户加载。js压缩,用到了uglifyjs-webpack-plugin,在optimization内进行配置。
(1)安装uglifyjs-webpack-pluginnpm install --save-dev uglifyjs-webpack-plugin (2)在webpack.prod.conf.js页面上引入const UglifyJSPlugin = require(‘uglifyjs-webpack-plugin‘); (3)optimization内配置minimizer参数minimizer: [ new UglifyJSPlugin() ], 你的optimization参数现在应该是这样: optimization: { minimizer: [ new UglifyJSPlugin() ],splitChunks: { chunks: "all",cacheGroups: { framework: { priority: 200,test: "framework",enforce: true,reuseExistingChunk: true },vendor: { priority: 10,test: /node_modules/,name: "vendor",reuseExistingChunk: true } } } } (4)重新执行npm run buildnpm run build ?
6.整合dev环境
?
我们不可能每次修改代码都去手动编译,等编译出来再去打开文件查看效果。webpack提供了开发环境服务,并且支持热更新,这在开发环境是非常有必要的。
webpack-dev-server这个模块提供了开发服务的支持,通过在webpack.dev.conf.js文件配置devServer可以方便地整合webpack-dev-server。 (1)安装webpack-dev-servernpm install --save-dev webpack-dev-server (2)在build中添加webpack.dev.conf.js文件const path = require(‘path‘); const merge = require(‘webpack-merge‘); const baseWebpackConfig = require(‘./webpack.base.conf.js‘); const HtmlWebpackPlugin = require(‘html-webpack-plugin‘); const webpack = require(‘webpack‘); module.exports = merge(baseWebpackConfig,{ mode: ‘development‘,output: { filename: "js/[name].[hash:16].js",minify: { html5: true },hash: false }),new webpack.HotModuleReplacementPlugin() ],devServer: { port: ‘8080‘,contentBase: path.join(__dirname,‘../public‘),compress: true,historyApiFallback: true,hot: true,https: false,noInfo: true,open: true,proxy: {} } }); HotModuleReplacementPlugin是webpack热更新的插件,设置devServer.hot为true,并且在plugins中引入HotModuleReplacementPlugin插件即可。 (3)在package.json增加一个npm scripts"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", (4)执行dev命令npm run dev 打开 http://localhost:8080 查看,你可以尝试改动index.js的代码,浏览器自动更新了,说明整合webpack-dev-server成功。 你可能注意到,对于css相关的技术栈,我只字未提,别急,下一节我们会详细针对css相关的技术栈进行整合。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |