webpack开发环境和生产环境的深入理解
若水若鱼 人气:0以前自己写一小项目时,webpack的配置基本就是一套配置,没有考虑生产环境和开发环境的区分,最近在做一个复杂的商城项目接触到了webpack的高级配置,经过两天的研究,写出了一份目前来说比叫满意的配置,在这里分享一下。
如何区分开发环境和生产环境?
众所周知,webpack时基于node.js平台运行的,要区分开发环境和生产环境还要存,node入手。我们启动webpack时,都需要输入一些命令,npm run 、yarn start之类的,所以我们就从命令行入手,告诉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":{ ... } }
这样配置,当我们在命令行输入 npm run dev 和 npm run dist 时,就会附带一些参数到命令行中,有了参数,我们该如何拿到呢?那就要用到 node 的一个命令行参数解析引擎了。
minimist
minimist轻量级的命令行参数解析引擎
// test.js var args = require('minimist')(process.argv.slice(2)); console.log(args.hello); $ node test.js --env=production // production $ node test.js --env=development // development $ node test.js --env // true 注意:不是空字符串而是true
minimist会把参数解析成一个JSON对象:{key:value},有了这个JSON对象,我们就可以知道,当前的命令是要执行开发打包,还是生产打包了。
// webpack.config.js const webpack = require('webpack'); //当前项目的绝对路劲 const path = require('path'); // 命令行参数解析引擎 const argv = require('minimist')(process.argv.slice(2)); let env = 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(代码映射)
// 开发环境打包配置 const path = require('path'); const webpack = require('webpack'); const base = require('./webpack.config.base') const dfPath = require('./path') // webpack配置合并工具 const merge =require('webpack-merge') const RS = (...arg)=>path.resolve( __dirname , ...arg ) // 合并方式配置 let strategyMerge = merge.strategy({ entry: 'prepend' }); let config = { 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:[ // 模块热替换功能 new webpack.HotModuleReplacementPlugin() ], // 代码映射,方便报错时,找到对应的源代码 devtool: 'cheap-module-eval-source-map', devServer:{ // 服务器打包后,输出的资源路劲 publicPath:'/', open:true } }; // 导出合并后的webpack配置 module.exports = strategyMerge( base , config );
生产环境配置
相比开发环境,生产环境打包是要最后发布到服务器部署的代码,我们需要尽量保持代码简洁,加载性能最优,不需要调试辅助工具。
我们从这几个方面优化 :1.公共模块拆分,单独打包;2. css文件分离,单独打包输出;3.代码压缩;
// 生产环境配置 const webpack = require('webpack'); const base = require('./webpack.config.base') const path = require('path'); const dfPath = require('./path'); const merge = require('webpack-merge'); // 压缩工具 const ClosureCompilerPlugin = require('webpack-closure-compiler'); // css单独打包插件 const extractTextWebpackPlugin = require('extract-text-webpack-plugin'); const extractCSS = new extractTextWebpackPlugin('assets/css/[name]_[contenthash:6].css'); // weback合并配置 let strategyMerge = merge.strategy({ entry: 'replace', output: 'replace', module:{ rules: 'replace' } }); let config ={ 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(生产环境) 环境变量的快捷方式。 new webpack.EnvironmentPlugin({ NODE_ENV: 'production' }) ,new ClosureCompilerPlugin() ], devtool: 'source-map' }; module.exports = strategyMerge(base,config);
加载全部内容