webpack开发环境和生产环境的深入理解
以前自己写一小项目时,webpack的配置基本就是一套配置,没有考虑生产环境和开发环境的区分,最近在做一个复杂的商城项目接触到了webpack的高级配置,经过两天的研究,写出了一份目前来说比叫满意的配置,在这里分享一下。
如何区分开发环境和生产环境?
众所周知,webpack时基于node.js平台运行的,要区分开发环境和生产环境还要存,node入手。我们启动webpack时,都需要输入一些命令,npmrun、yarnstart之类的,所以我们就从命令行入手,告诉webpack,当前是什么环境。
package.json
{ "name":"webpac-demo", "version":"1.0.0", "description":"webpack练习", "main":"index.js", "scripts":{ //配置开发环境参数。注意:真实开发中package.json文件中不能有注释 "dev":"webpack--env=development", //配置生产环境参数 "dist":"webpack--env=production", "start":"webpack-dev-server--env=development" }, "dependencies":{ "font-awesome":"^4.7.0", "react":"^16.2.0", "react-dom":"^16.2.0" }, "devDependencies":{ ... } }
这样配置,当我们在命令行输入npmrundev和npmrundist时,就会附带一些参数到命令行中,有了参数,我们该如何拿到呢?那就要用到node的一个命令行参数解析引擎了。
minimist
minimist轻量级的命令行参数解析引擎
//test.js varargs=require('minimist')(process.argv.slice(2)); console.log(args.hello); $nodetest.js--env=production //production $nodetest.js--env=development //development $nodetest.js--env //true注意:不是空字符串而是true
minimist会把参数解析成一个JSON对象:{key:value},有了这个JSON对象,我们就可以知道,当前的命令是要执行开发打包,还是生产打包了。
//webpack.config.js constwebpack=require('webpack'); //当前项目的绝对路劲 constpath=require('path'); //命令行参数解析引擎 constargv=require('minimist')(process.argv.slice(2)); letenv=null; switch(argv.env){ case'production': //生产环境配置文件名 env='webpack.config.prod'; break; default: //开发环境配置文件名 env='webpack.config.dev'; } console.log(`当前是${argv.env}打包`); //这时候,我们就可以加载相应的wabpack配置了。 module.exports=require(path.resolve('加载的配置文件路劲',env));
webpack开发环境配置和生产环境配置
开发环境配置
在开发环境下,我们首先考虑的是方便开发,方便代码调试,不需要考虑代码合并和css样式分离这些。
这里主要说三个:1.css模块化;2.模块热替换功能;3.source-map(代码映射)
//开发环境打包配置 constpath=require('path'); constwebpack=require('webpack'); constbase=require('./webpack.config.base') constdfPath=require('./path') //webpack配置合并工具 constmerge=require('webpack-merge') constRS=(...arg)=>path.resolve(__dirname,...arg) //合并方式配置 letstrategyMerge=merge.strategy({ entry:'prepend' }); letconfig={ entry:{ app:path.resolve(dfPath.root,'src/app.js') }, output:{ path:dfPath.dist, filename:'[name].bundle.js', publicPath:'/', chunkFilename:'[name].sepChunk.js' }, module:{ rules:[ { test:/\.js$/, use:['babel-loader'], exclude:[ dfPath.node_modules ] }, { test:/\.css$/, use:[ 'style-loader', { loader:'css-loader', options:{ //css模块化,方便多人开发 module:true, //定义模块化css后的类名(默认为hash值,可读性差)path:路劲;name:文件名;local:本地定义的className localIdentName:'[path][name]__[local]--[hash:base64:5]' }, } ], //排除的文件,遇到这些文件不会用当前loader处理,也就不会模块化 exclude:[ RS('./src/common'), RS('node_modules') ] }, { test:/\.css$/, use:['style-loader','css-loader'], include:[ RS('./src/common'), RS('node_modules') ] }, { test:/\.(png|jpg|jpeg|gif)$/, use:['url-loader?limit=8192'], } ] }, plugins:[ //模块热替换功能 newwebpack.HotModuleReplacementPlugin() ], //代码映射,方便报错时,找到对应的源代码 devtool:'cheap-module-eval-source-map', devServer:{ //服务器打包后,输出的资源路劲 publicPath:'/', open:true } }; //导出合并后的webpack配置 module.exports=strategyMerge(base,config);
生产环境配置
相比开发环境,生产环境打包是要最后发布到服务器部署的代码,我们需要尽量保持代码简洁,加载性能最优,不需要调试辅助工具。
我们从这几个方面优化:1.公共模块拆分,单独打包;2.css文件分离,单独打包输出;3.代码压缩;
//生产环境配置 constwebpack=require('webpack'); constbase=require('./webpack.config.base') constpath=require('path'); constdfPath=require('./path'); constmerge=require('webpack-merge'); //压缩工具 constClosureCompilerPlugin=require('webpack-closure-compiler'); //css单独打包插件 constextractTextWebpackPlugin=require('extract-text-webpack-plugin'); constextractCSS=newextractTextWebpackPlugin('assets/css/[name]_[contenthash:6].css'); //weback合并配置 letstrategyMerge=merge.strategy({ entry:'replace', output:'replace', module:{ rules:'replace' } }); letconfig={ entry:{ //公共模块拆分,这些代码会单独打包,一般我们会把引用的框架文件拆分出来,方便浏览器缓存,节省资源。 vender:['react'], app:path.resolve(dfPath.root,'src/app.js') }, output:{ path:dfPath.dist, filename:'assets/js/[name]_[chunkhash].bundle.js', publicPath:'/', chunkFilename:'assets/js/[name].sepChunk.js', hashDigestLength:6 }, module:{ rules:[ { test:/\.js$/, use:['babel-loader'], exclude:[ dfPath.node_modules ] }, /*开启css单独打包和css模块化的配置*/ { test:/\.css$/, use:extractCSS.extract({ use:[ { loader:'css-loader', options:{ modules:true } } ] }) }, { test:/\.(png|jpg|jpeg|gif)$/, use:[ { loader:'url-loader', options:{ limit:8192, name:'[name]_[hash].[ext]', outputPath:'assets/img/' } } ], }, { test:/\.(mp4|ogg|svg|ico)$/, use:[ { loader:'file-loader', options:{ name:'[name]_[hash].[ext]', outputPath:'assets/media/' } } ] }, { test:/\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, use:[ { loader:'url-loader', options:{ limit:10000, name:'[name]_[hash].[ext]', outputPath:'assets/font/', mimetype:'application/font-woff' } } ] }, { test:/\.ttf(\?v=\d+\.\d+\.\d+)?$/, use:[ { loader:'url-loader', options:{ limit:10000, name:'[name]_[hash].[ext]', outputPath:'assets/font/', mimetype:'application/octet-stream' } } ] }, { test:/\.eot(\?v=\d+\.\d+\.\d+)?$/, use:[ { loader:'file-loader', options:{ name:'[name]_[hash].[ext]', outputPath:'assets/font/', } } ] }, { test:/\.svg(\?v=\d+\.\d+\.\d+)?$/, use:[ { loader:'url-loader', options:{ limit:10000, name:'[name]_[hash].[ext]', outputPath:'assets/font/', mimetype:'image/svg+xml' } } ] }, ] }, plugins:[ extractCSS, //设置process.env(生产环境)环境变量的快捷方式。 newwebpack.EnvironmentPlugin({ NODE_ENV:'production' }) ,newClosureCompilerPlugin() ], devtool:'source-map' }; module.exports=strategyMerge(base,config);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。