1.为什么需要webpack
webpack是前端打包工具,通过分析所在项目的目录结构,找到模块及各模块间的依赖关系,且将浏览器不能直接运行的语言如typescript、css预处理器语法(less、sass)等或者因为浏览器因为版本底不支持新的内置函数,需要将其转换及打包成浏览器支持格式
接下来介绍下vue不同版本脚手架webpack使用配置的区别
左图项目结构为vue-cli 2x版本脚手架生成的项目,build文件夹包含了webpack配置
右图项目结构为vue-cli 3x版本脚手架生成的项目,3x版本并不存在该文件,而是将其配置集成到vue.config.js中
webpack配置文件有三个
针对不同环境的配置,运行不同的配置文件
(1)webpack.base.conf.js 结构
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader', {
loader: 'postcss-loader',
options: {
plugins: () => [
require('autoprefixer')({
overrideBrowserslist: ['last 2 versions', '>1%']
})
]
}
}]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
]
},
plugins: [
new HtmlWebpackPlugin({
title: '首页',
template: 'index.html',
filename: 'index.html'
}),
new CleanWebpackPlugin(),
]
}
复制代码
涉及到的配置知识
babel-loader:解析 .js 和 .jsx 文件
tsx-loader:处理 ts 文件
less-loader:处理 less 文件,并将其编译为 css
sass-loader:处理 sass、scss 文件,并将其编译为 css
postcss-loader:// 解析CSS文件并且添加浏览器前缀到 CSS 内容里
module.exports = {
plugins: [require('autoprefixer')],
};
css-loader:处理 css 文件
style-loader:将 css 注入到 DOM
file-loader:将文件上的import / require 解析为 url,并将该文件输出到输出目录中
url-loader:用于将文件转换成 base64 uri 的 webpack 加载程序
html-loader:将 HTML 导出为字符串, 当编译器要求时,将 HTML 最小化
复制代码
(2) webpack.dev.conf.js 结构
开发环境的webpack配置文件,依赖了base.conf,需要将其合并后再执行
'use strict'
// webpack.dev.js
const webpack = require('webpack')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const devWebpackConfig = merge(baseWebpackConfig, {
devServer: {
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: '0.0.0.0',
port: 8080,
open: true,
},
})
复制代码
开发环境时,如上所示,需要配置devServer属性,通过webpack-dev-server 的这些选项改变,来改变其行为,常用配置有:
更多配置前往 官网dev-server配置
(3) webpack.prod.conf.js 结构
// webpack.prod.conf.js
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const env = require('../config/prod.env');
const Version = new Date().getTime();
const webpackConfig = merge(baseWebpackConfig, {
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash]'+ Version+'.js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash]'+ Version+'.js')
},
plugins: [
new UglifyJsPlugin(),
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash]'+Version+'.css'),
allChunks: true,
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
module.exports = webpackConfig
复制代码
常用plugins插件的功能分解:
webpack编译过程中设置全局变量process.env
new webpack.DefinePlugin({
'process.env': require('../config/dev.env.js')
}
复制代码
或者通过命令行配置(用到cross-env)
cross-env NODE_ENV=production webpack --config webpack.config.prod.js
复制代码
new HtmlWebpackPlugin({
title: '首页',
template: 'index.html',
filename: 'index.html'
}),
复制代码
生成 html 文件,并将包添加到 html 中
运行webpack命令行工具,前一章讲了webpack配置的用法,下面是CLI 用法,两者可替代
webpack-dev-server //启动开发服务器
--open //打开浏览器
--config webpack.dev.js //设置运行此脚本时执行的配置文件为webpack.dev.js
--progress //显示进度条
复制代码
vue-cli3 创建的时候并不会自动创建vue.config.js,因为这个是个可选项,需要修改webpack的时候才会自己创建一个vue.config.js,把webpack的配置加入到vue.config.js
// vue.config.js
const path = require('path');
function resolve(dir) {
return path.join(__dirname, '.', dir);
}
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
outputDir: 'dist',
runtimeCompiler: false,
productionSourceMap: false,
chainWebpack: (config) => {
config.output.filename('[name].[hash].js').end();
config.resolve.alias.set('@', path.resolve('src'));// 添加别名
config.entry('main').add('babel-polyfill');
},
configureWebpack: () => {
if (process.env.NODE_ENV === 'production') {
return {
plugins: [
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
test: productionGzipExtensions,
threshold: 2048,
minRatio: 0.8,
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
drop_debugger: true,
drop_console: true,
},
sourceMap: false,
parallel: true,
},
}),
],
};
}
return false;
},
css: {
extract: true,
sourceMap: false,
modules: false,
},
devServer: {
port: 8088,
host: '0.0.0.0',
hotOnly: false,
},
pluginOptions: {
// ...
}
};
复制代码
通过process.env.NODE_ENV 去区分环境不同执行不同的命令