JavaScript

超轻量级php框架startmvc

webpack开发环境和生产环境的深入理解

更新时间:2020-08-04 10:54 作者:startmvc
以前自己写一小项目时,webpack的配置基本就是一套配置,没有考虑生产环境和开发环境的

以前自己写一小项目时,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);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。