開發環境和生產環境的構建目標是有很大的不一樣的。javascript
在開發環境中,爲了便於代碼調試以及實現瀏覽器實時更新,咱們須要開啓 source map
和 localhost server
。css
而在生成環境中,爲了實現緩存優化以及改善加載時間,咱們的目標轉向於打包成更小的 bundle
或 chunk
,分離第三方包以及開啓更輕量級的 source map
以及更優化的資源。html
所以開發環境和生產環境須要單獨配置 webpack。java
假設項目打包需求以下:node
公共部分:webpack
html-webpack-plugin
)postcss-loader
sass-loader
css-loader
style-loader
)url-loader
file-loader
)ts-loader
)在開發環境下:git
source map
devServer
在生產環境下:github
mini-css-extract-plugin
SplitChunksPlugin
)根據以上狀況,咱們須要定義三個webpack配置文件,分別是:web
webpack.base.conf.jstypescript
用來配置開發模式和生產模式的wenpack公共配置
webpack.dev.conf.js
用來專門配置開發模式所需的webpack配置
webpack.prod.conf.js
用來專門配置生產模式所需的webpack配置
--demo19
--build
-config.js
-webpack.base.conf.js //公共配置
-webpack.dev.conf.js //開發環境
-webpack.prod.conf.js //生產環境
--src
--app
-app.ts
--assets
--fonts // 字體相關
-icomoon.css
-icomoon.eot
-icomoon.svg
-icomoon.ttf
-icomoon.woff
--images // 圖片相關
-1.png //18.6KB
-2.png //12.1KB
-3.png //14.9KB
-me.jpg //2.58MB
--styles
-app.scss
-index.html
-postcss.config.js // 處理 css 前綴
-tsconfig.json // 處理 ts
複製代碼
代碼放在github上
npm install -D css-loader style-loader node-sass sass-loader // 處理scss
npm install -D postcss postcss-loader autoprefixer // 處理css前綴
npm install -D file-loader url-loader // 處理字體和圖片
npm install -D ts-loader typescript // 處理ts
npm install -D html-webpack-plugin clean-webpack-plugin // 自動生成html文件以及清除dist目錄
npm install -D webpack-dev-server // devServer
npm install -D mini-css-extract-plugin // 分離css爲單獨的文件
npm install -D optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin // 壓縮css和js文件
npm install -D webpack-merge // 合併webpack配置: base + dev 或 base + prod
npm install -D webpack webpack-cli
複製代碼
'use strict'
const path = require("path");
const isDev = /^dev/.test(process.env.npm_lifecycle_event);
const config = require('./config');
const CleanWebpackPlugin = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: isDev ? "development" : "production", // 開發模式
entry: {
app: "./src/app/app.ts"
},
output: {
publicPath: isDev ? config.dev.publicPath : config.prod.publicPath, // 打包後資源文件的引用會基於此路徑
path: path.resolve(__dirname, "..", "dist"), // 打包後的輸出目錄
filename: isDev ? config.dev.filename : config.prod.filename,// 在development模式下,id爲name
chunkFilename: isDev ? config.dev.chunkFilename : config.prod.chunkFilename
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{ test: /\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader' },
{
test: /\.(jpg|png|gif|bmp|jpeg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 20000, // size <= 20KB
name: '[name].[hash].[ext]', // 屬於file-loader的屬性
publicPath: "imgs/", // 屬於file-loader的屬性
outputPath: "imgs/" // 屬於file-loader的屬性
}
}
]
},
{
test: /\.ts?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
plugins: [
new HtmlWebpackPlugin({ // 自動生成html,而且自動導入全部依賴同步包
filename: "index.html",
template: path.resolve(__dirname, "../src", "index.html"),
minify: {
collapseWhitespace: true // 壓縮
}
}),
new CleanWebpackPlugin()
]
};
複製代碼
'use strict'
const path = require('path');
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const devWebpackConfig = merge(baseWebpackConfig, {
devtool: "source-map",
devServer: {
contentBase: path.join(__dirname, "../dist/"),
port: 8000,
hot: false,
overlay: true,
historyApiFallback: {
rewrites: [{ from: /.*/, to: "/index.html" }]
}
},
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
"style-loader",
"css-loader", // 將 CSS 轉化成 js 模塊
{
loader: 'postcss-loader' // 配置在postcss.config.js
},
"sass-loader" // 將 Sass/Scss 編譯成 CSS
]
}
]
},
plugins: []
});
module.exports = devWebpackConfig;
複製代碼
'use strict'
const merge = require('webpack-merge');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const baseWebpackConfig = require('./webpack.base.conf')
const prodWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader, // 將css提取爲單獨的文件
"css-loader", // 將 CSS 轉化成 js 模塊
{
loader: 'postcss-loader',// 配置在postcss.config.js
},
"sass-loader" // 將 Sass/Scss 編譯成 CSS
]
}
]
},
optimization: {
runtimeChunk: "single", // webpack運行時代碼單獨提取爲一個包
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: false // set to true if you want JS source maps
}),
new OptimizeCSSAssetsPlugin({})
],
splitChunks: {
cacheGroups: {
async: {
chunks: "async",
maxInitialRequests: 3, // 設置最大的請求數
automaticNameDelimiter: '~',
priority: 9
},
vendors: {
chunks: "all", // 使用 all 模式
test: /[\\/]node_modules[\\/]/, // 匹配 node_modules 下的模塊
name: "vendors", // 包命名,最終的命名要結合 output 的 chunkFilename
priority: 10 // 設置優先級
}
}
}
},
plugins: [
new MiniCssExtractPlugin({
filename: "[id].[name].[chunkhash:8].css",
chunkFilename: "[id].[name].[chunkhash:8].css"
})
]
});
module.exports = prodWebpackConfig;
複製代碼
在 package.json 中添加以下 npm scripts
"scripts": {
"dev": "webpack-dev-server --open --inline --progress --config build/webpack.dev.conf.js",
"prod": "webpack --config build/webpack.prod.conf.js"
},
複製代碼
執行以下命令,開啓開發調試模式,自動打開瀏覽器,當修改代碼時,瀏覽器自動刷新,便於開發和調試。
npm run dev
複製代碼
執行以下命令,webpack將以production模式進行打包,實現代碼壓縮,分離第三方模塊以及css爲單獨的chunk,這樣有利於對單獨的包進行緩存優化。
npm run prod
複製代碼
demo 代碼地址: github.com/SimpleCodeC…
倉庫代碼地址(及目錄): github.com/SimpleCodeC…