本文接前篇 webpack構建技巧之開發篇,但可獨立使用。
項目目錄:
一、入口
入口與開發篇相同
function resolve(dir) {
return path.join(__dirname, '..', dir) //返回的是項目目錄下的文件夾
}
module.exports = {
entry: resolve('src/main.js')
}
二、出口
出口與開發篇有點差別
output: {
path: resolve('dist'),
filename: 'static/js/[name].[hash:8].js',
chunkFilename: 'static/js/[name].[hash:8].chunk.js',
publicPath: "./"
},
關於publicPath:
公共路徑,它會在你所有的路徑前加指定參數。看圖:
這是 publicPath = ' ./ ' 下的文件路徑
這是默認的,也就是 publicPath = ' ' 下的文件路徑:
三、module
其他的處理除css外與開發篇相同,以下就僅僅把代碼貼上:
{
test: /\.(htm|html)$/i,
use: [{
loader: 'html-withimg-loader'
}]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
include: /\src/,
use: {
loader: 'babel-loader',
}
},
{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
limit: 10000,
name: 'static/img/[name].[hash:8].[ext]',
}
}]
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'static/media/[name].[ext]'
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'static/fonts/[name].[ext]'
}
},
對於css的處理:
我們更多的情況下是會引入外部的css文件,這裏處理的目的就是把多個css文件處理成一個文件並用外聯的方法引入。
首先,提取css,webpack4+用 mini-css-extract-plugin 這個插件,其他使用 extract-text-webpack-plugin 這個插件。
webpack4+:
在前面引入插件
//webpack 4+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
//webpack 4-
const ExtractTextPlugin = require('extract-text-webpack-plugin')
{
test: /\.(css|less)$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../../' //這個publicPath是爲了解決css中引入背景圖的路徑問題
}
},
'css-loader',
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9',
],
flexbox: 'no-2009',
}),
],
},
},
'less-loader'
],
},
webpack4-:
{
test: /\.(css|less)$/,
loader: ExtractTextPlugin.extract(
Object.assign({
fallback: {
loader: require.resolve('style-loader'),
options: {
hmr: false,
},
},
publicPath:'../../', //接css引入背景圖的路徑問題
use: [
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
minimize: true
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9',
],
flexbox: 'no-2009',
}),
],
},
},
{
loader: require.resolve('less-loader'),
},
],
}, )
),
},
然後在plugins中生成css文件:
new MiniCssExtractPlugin({
filename: 'static/css/[name].[hash:8].css'
}),
new ExtractTextPlugin({
filename: 'static/css/[name].[hash:8].css'
}),
關於publicPath:
假設你在開發中寫如如下背景圖樣式:
顯然這在線上環境中是那不到的,因爲這個路徑是在css文件中被引用的,你得加上相對路徑參數,在我的文件夾目錄下是這樣的:
各個文件夾結構不相同,你可以靈活選擇。
三、plugins
這裏用於處理並壓縮文件:
js:
在webpack4-中使用 uglifyjs-webpack-plugin這個插件,然後直接在plugins中使用就ok
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
plugins: {
new UglifyJsPlugin()
}
optimization(webpack4+)
在webpack4+中移除了 uglifyjs-webpack-plugin 方法,採用optimization中對js壓縮,提取,去重,方法如下:
optimization: {
minimize: true, //壓縮js,默認使用uglifyjs-webpack-plugin插件
splitChunks: {
cacheGroups: { //定義規則
vendors: { //提取node_modules中對js生成chunk-vndord文件夾
name: 'chunk-vendors',
test: /[\\\/]node_modules[\\\/]/,
priority: -10,
chunks: 'all'
},
common: { //提取公共部分js生成chunk-common文件夾
name: 'chunk-common',
minChunks: 2,
priority: -20,
chunks: 'all',
reuseExistingChunk: true
},
styles: { //提取less或css合成一個layout.css文件
name: 'layout',
test: /\.(less|css)$/,
chunks: 'all',
minChunks: 1,
reuseExistingChunk: true,
enforce: true
}
}
}
},
最後生成的文件夾目錄結構如下圖:
css:
提取css已經在module中說明,這裏說一下壓縮:安裝插件 optimize-css-assets-webpack-plugin
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
new OptimizeCSSPlugin({
cssProcessorOptions: {safe: true, map: {inline: false}}
}),
html:
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html', //本地自定義模板
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
},
chunksSortMode: 'dependency' //定義引入文件順序,按依賴排序
}),
其他:
//複製靜態文件
new CopyWebpackPlugin([{
from: resolve('static'),
to: resolve('dist/static'),
ignore: ['.*']
}]),
//生成文件索引文件
new ManifestPlugin({
fileName: 'asset-manifest.json',
}),
最後,由於每次修改後打包加了hash值,每次文件加都不一樣,就會造成每打包一次就會新增加一個相同文件,類似於這樣:
我們在打包之前先做一步,就是把現有的dist文件夾移除掉,新建一個build.js文件,這裏用到一個插件 rimraf
const webpack = require('webpack');
const path = require('path');
const webpackConfig = require('./webpack.pro.conf');
const rm = require('rimraf');
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
rm(resolve('dist'), err => {
if (err) throw err
webpack(webpackConfig, err => {
if (err) throw err
})
})
構建基本完成,改下命令行:
//package.json
"build": "node config/build.js"
npm run build 就可以生成你的項目生產版本。
這可能是一個最簡單的版本,還可以做很多優化的地方,webpack中還有很多有趣的插件,希望看完不吝指正,多謝!
完整版本請移步:https://github.com/linxner/webpackENV
最後,附上所有webpack.pro.conf.js代碼:
//webpack.pro.conf.js
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const autoprefixer = require('autoprefixer')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const ManifestPlugin = require('webpack-manifest-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: resolve('src/main.js'),
output: {
path: resolve('dist'),
filename: 'static/js/[name].[hash:8].js',
chunkFilename: 'static/js/[name].[hash:8].chunk.js',
publicPath: "./"
},
module: {
rules: [
{
test: /\.(htm|html)$/i,
use: [{
loader: 'html-withimg-loader'
}]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
include: /\src/,
use: {
loader: 'babel-loader',
}
},
{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
limit: 10000,
name: 'static/img/[name].[hash:8].[ext]',
}
}]
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'static/media/[name].[ext]'
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'static/fonts/[name].[ext]'
}
},
{
test: /\.(css|less)$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../../'
}
},
'css-loader',
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9',
],
flexbox: 'no-2009',
}),
],
},
},
'less-loader'
],
},
],
},
mode: "production",
optimization: {
minimize: true,
splitChunks: {
cacheGroups: {
vendors: {
name: 'chunk-vendors',
test: /[\\\/]node_modules[\\\/]/,
priority: -10,
chunks: 'all'
},
common: {
name: 'chunk-common',
minChunks: 2,
priority: -20,
chunks: 'all',
reuseExistingChunk: true
},
styles: {
name: 'layout',
test: /\.(less|css)$/,
chunks: 'all',
minChunks: 1,
reuseExistingChunk: true,
enforce: true
}
}
}
},
plugins: [
new MiniCssExtractPlugin({
filename: 'static/css/[name].[hash:8].css',
}),
new OptimizeCSSPlugin({
cssProcessorOptions: {safe: true, map: {inline: false}}
}),
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html', //本地自定義模板
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
},
chunksSortMode: 'dependency'
}),
new CopyWebpackPlugin([{
from: resolve('static'),
to: resolve('dist/static'),
ignore: ['.*']
}]),
new ManifestPlugin({
fileName: 'asset-manifest.json',
}),
],
}