開發環境(development)和生産環境(production)的建構目标差異很大。在開發環境中,我們需要具有強大的、具有實時重新加載(live reloading)或熱子產品替換(hot module replacement)能力的 source map 和 localhost server。而在生産環境中,我們的目标則轉向于關注更小的 bundle,更輕量的 source map,以及更優化的資源,以改善加載時間。由于要遵循邏輯分離,我們通常建議為每個環境編寫彼此獨立的 webpack 配置。
雖然,以上我們将生産環境和開發環境做了略微區分,但是,請注意,我們還是會遵循不重複原則(Don’t repeat yourself - DRY),保留一個“通用”配置。為了将這些配置合并在一起,我們将使用一個名為 webpack-merge 的工具。通過“通用”配置,我們不必在環境特定(environment-specific)的配置中重複代碼。
注:示例的完整代碼請參考《Webpack整合執行個體及優化》
安裝
推薦使用項目局部安裝:在 package.json 中添加如下配置,并進行安裝
“webpack-merge”: “^4.1.1”,
配置檔案分離
webpack.common.js
const path = require("path");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
app: "./js/requireAddDiv.js"
},
module: {
rules: [
{
test: /\.(jsx|js)$/,
use: {
loader: "babel-loader?cacheDirectory=true", // 使用cache提升編譯速度
options: {
presets: ["env", "react"],
plugins: ["transform-runtime"]// 避免重複引入
}
},
exclude: /node_modules/
},
{// 分離 css
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},
{
test: /\.html$/,
use: "html-loader"
}
]
},
plugins: [
new CleanWebpackPlugin(["dist"]),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "index.temp.html")
})
]
};
webpack.dev.js
const merge = require("webpack-merge");
const common = require("./webpack.common");
const path = require("path");
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = merge(common, {
devtool: "eval-source-map", // 僅在開發過程中使用
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.[hash].js"
},
devServer: {
contentBase: "./",
historyApiFallback: true,
inline: true
// hot: true // hot module replacement. Depends on HotModuleReplacementPlugin
},
module: {
rules: [
{// 處理圖檔,會在 output 目錄中生成圖檔檔案,js 中需要使用 require("*.jpg")先行引入才可以,同樣 html 中通過 background-image 設定的圖檔不可以,但 css 中通過 background-image 設定的圖檔可以
test: /\.(jpg|png)$/,
use: {
loader: "file-loader",
options: {
outputPath: "images/", // 這裡的 images 貌似沒什麼作用,但不寫不行,可以是任意的一個或多個字元
name: "[name].[hash:8].[ext]", // 8表示截取 hash 的長度
useRelativePath: true// 這個必須與 outputPath 結合使用才可以處理 css 中的引入的圖檔
}
}
}
]
},
plugins: [
new ExtractTextPlugin("css/styles-[hash].css") // 可以單獨設定css的路徑
// new webpack.NamedModulesPlugin(), // 以便更容易檢視要修補(patch)的依賴
// new webpack.HotModuleReplacementPlugin() // 使用 hot 導緻頁面不能自動重新整理?
]
});
webpack.prod.js
const merge = require("webpack-merge");
const common = require("./webpack.common");
const path = require("path");
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = merge(common, {
devtool: "source-map",//生産環境也可以設定,有點兒影響性能,但友善調試
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
},
module: {
rules: [
{// 處理圖檔,會在 output 目錄中生成圖檔檔案,js 中需要使用 require("*.jpg")先行引入才可以,同樣 html 中通過 background-image 設定的圖檔不可以,但 css 中通過 background-image 設定的圖檔可以
test: /\.(jpg|png)$/,
use: {
loader: "file-loader",
options: {
outputPath: "images/", // 這裡的 images 貌似沒什麼作用,但不寫不行,可以是任意的一個或多個字元
name: "[name].[ext]",
useRelativePath: true// 這個必須與 outputPath 結合使用才可以處理 css 中的引入的圖檔
}
}
}
]
},
plugins: [
new webpack.BannerPlugin("版權所有,盜版必究!"),
new webpack.DefinePlugin({
"process.env": {
"NODE_ENV": JSON.stringify("production")
}
}),
// new webpack.optimize.OccurrenceOrderPlugin(), // 現在是預設啟用,不再需要手動啟動
new webpack.optimize.UglifyJsPlugin({
output: {
comments: false// remove all comments
},
compress: {
warnings: false
},
sourceMap: true // 如果你在壓縮代碼時啟用了 source map,或者想要讓 uglifyjs 的警告能夠對應到正确的代碼行,你需要将 UglifyJsPlugin 的 sourceMap 設為 true。
}),
new ExtractTextPlugin("css/styles.css") // 可以單獨設定css的路徑
]
});
package.json
{
"name": "webpack",
"version": "1.0.0",
"description": "This is just a test",
"main": "dist/bundle.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --open --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
},
"keywords": [
"webpack",
"dev-server"
],
"author": "slHuang",
"license": "ISC",
"devDependencies": {
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.4",
"webpack-merge": "^4.1.1",
"style-loader": "^0.19.0",
"css-loader": "^0.28.7",
"postcss-loader": "^2.0.8",
"autoprefixer": "^7.1.6",
"babel-core": "^6.26.0",
"babel-cli": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-react": "^6.24.1",
"babel-preset-env": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"babel-plugin-transform-runtime": "^6.23.0",
"extract-text-webpack-plugin": "^3.0.2",
"clean-webpack-plugin": "^0.1.17",
"html-loader": "^0.5.1",
"file-loader": "^1.1.5",
"eslint": "^4.11.0"
},
"dependencies": {
"babel-runtime": "^6.26.0"
}
}
運作 start 為開發環境,
運作 build 為生産環境。