webpack開發(fā)環(huán)境和生產(chǎn)環(huán)境的深入理解
以前自己寫一小項(xiàng)目時(shí),webpack的配置基本就是一套配置,沒有考慮生產(chǎn)環(huán)境和開發(fā)環(huán)境的區(qū)分,最近在做一個(gè)復(fù)雜的商城項(xiàng)目接觸到了webpack的高級(jí)配置,經(jīng)過兩天的研究,寫出了一份目前來說比叫滿意的配置,在這里分享一下。
如何區(qū)分開發(fā)環(huán)境和生產(chǎn)環(huán)境?
眾所周知,webpack時(shí)基于node.js平臺(tái)運(yùn)行的,要區(qū)分開發(fā)環(huán)境和生產(chǎn)環(huán)境還要存,node入手。我們啟動(dòng)webpack時(shí),都需要輸入一些命令,npm run 、yarn start之類的,所以我們就從命令行入手,告訴webpack,當(dāng)前是什么環(huán)境。
package.json
{
"name": "webpac-demo",
"version": "1.0.0",
"description": "webpack練習(xí)",
"main": "index.js",
"scripts": {
//配置開發(fā)環(huán)境參數(shù)。注意:真實(shí)開發(fā)中 package.json 文件中不能有注釋
"dev": "webpack --env=development",
//配置生產(chǎn)環(huán)境參數(shù)
"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":{
...
}
}
這樣配置,當(dāng)我們?cè)诿钚休斎?npm run dev 和 npm run dist 時(shí),就會(huì)附帶一些參數(shù)到命令行中,有了參數(shù),我們?cè)撊绾文玫侥兀磕蔷鸵玫?node 的一個(gè)命令行參數(shù)解析引擎了。
minimist
minimist輕量級(jí)的命令行參數(shù)解析引擎
// 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會(huì)把參數(shù)解析成一個(gè)JSON對(duì)象:{key:value},有了這個(gè)JSON對(duì)象,我們就可以知道,當(dāng)前的命令是要執(zhí)行開發(fā)打包,還是生產(chǎn)打包了。
// webpack.config.js
const webpack = require('webpack');
//當(dāng)前項(xiàng)目的絕對(duì)路勁
const path = require('path');
// 命令行參數(shù)解析引擎
const argv = require('minimist')(process.argv.slice(2));
let env = null;
switch (argv.env) {
case 'production':
//生產(chǎn)環(huán)境配置文件名
env = 'webpack.config.prod';
break;
default:
//開發(fā)環(huán)境配置文件名
env = 'webpack.config.dev';
}
console.log(`當(dāng)前是 ${argv.env} 打包`);
// 這時(shí)候,我們就可以加載相應(yīng)的wabpack配置了。
module.exports = require( path.resolve( '加載的配置文件路勁',env ) );
webpack開發(fā)環(huán)境配置和生產(chǎn)環(huán)境配置
開發(fā)環(huán)境配置
在開發(fā)環(huán)境下,我們首先考慮的是方便開發(fā),方便代碼調(diào)試,不需要考慮代碼合并和css樣式分離這些。
這里主要說三個(gè) :1.css模塊化;2.模塊熱替換功能;3.source-map(代碼映射)
// 開發(fā)環(huán)境打包配置
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模塊化,方便多人開發(fā)
module:true,
// 定義模塊化css后的類名(默認(rèn)為hash值,可讀性差)path:路勁; name:文件名; local:本地定義的className
localIdentName: '[path][name]__[local]--[hash:base64:5]'
},
}
],
// 排除的文件,遇到這些文件不會(huì)用當(dāng)前 loader 處理,也就不會(huì)模塊化
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()
],
// 代碼映射,方便報(bào)錯(cuò)時(shí),找到對(duì)應(yīng)的源代碼
devtool: 'cheap-module-eval-source-map',
devServer:{
// 服務(wù)器打包后,輸出的資源路勁
publicPath:'/',
open:true
}
};
// 導(dǎo)出合并后的webpack配置
module.exports = strategyMerge( base , config );
生產(chǎn)環(huán)境配置
相比開發(fā)環(huán)境,生產(chǎn)環(huán)境打包是要最后發(fā)布到服務(wù)器部署的代碼,我們需要盡量保持代碼簡(jiǎn)潔,加載性能最優(yōu),不需要調(diào)試輔助工具。
我們從這幾個(gè)方面優(yōu)化 :1.公共模塊拆分,單獨(dú)打包;2. css文件分離,單獨(dú)打包輸出;3.代碼壓縮;
// 生產(chǎn)環(huán)境配置
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單獨(dú)打包插件
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: {
// 公共模塊拆分,這些代碼會(huì)單獨(dú)打包,一般我們會(huì)把引用的框架文件拆分出來,方便瀏覽器緩存,節(jié)省資源。
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單獨(dú)打包 和 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,
// 設(shè)置 process.env(生產(chǎn)環(huán)境) 環(huán)境變量的快捷方式。
new webpack.EnvironmentPlugin({
NODE_ENV: 'production'
})
,new ClosureCompilerPlugin()
],
devtool: 'source-map'
};
module.exports = strategyMerge(base,config);
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript實(shí)現(xiàn)生成GUID(全局統(tǒng)一標(biāo)識(shí)符)
這篇文章主要介紹了JavaScript實(shí)現(xiàn)生成GUID(全局統(tǒng)一標(biāo)識(shí)符),本文寫成了一個(gè)GUID生成類,使用也非常方便,需要的朋友可以參考下2014-09-09
基于Bootstrap使用jQuery實(shí)現(xiàn)簡(jiǎn)單可編輯表格
這篇文章主要介紹了基于Bootstrap使用jQuery實(shí)現(xiàn)簡(jiǎn)單可編輯表格的相關(guān)資料,需要的朋友可以參考下2016-05-05
Typescript中使用引用路徑別名報(bào)錯(cuò)的解決方法
本文主要介紹了Typescript中使用引用路徑別名報(bào)錯(cuò)的解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
全面了解構(gòu)造函數(shù)繼承關(guān)鍵apply call
下面小編就為大家?guī)硪黄媪私鈽?gòu)造函數(shù)繼承關(guān)鍵apply call。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-07-07
JavaScript學(xué)習(xí)筆記之圖片庫案例分析
這篇文章主要介紹了JavaScript學(xué)習(xí)筆記之圖片庫案例,結(jié)合具體實(shí)例形式分析了javascript圖片庫相關(guān)的頁面元素動(dòng)態(tài)操作實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-01-01

