本文接前篇 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',
}),
],
}