webpack打包的原理:webpack都有entry、module、loader、chunk、output等配置选项。 webpack首先会根据entry找到对应所依赖的module(webpack会把所有的文件看多模块)进行递归解析,比如main.js、main.ts等等,同时也会根据loader对应的转换规则去转换,这些模块会以entry为单位进行分组,一个entry和其所有依赖的module被分到一个组,也就是一个chunk,最后webpack会把所有chunk转换成文件输出,在整个流程中webpack会在恰当的实际执行plugin定义的逻辑
多种配置类型
导出一个函数
module.exports = function(env,argv){
return {
mode: env.production? 'production': 'development'
entry: './src/main.js',
resolve: {
},
module: {
rules: [
{
test: /\.json$/,
use: 'json-loader'
},
]
},
plugins: []
}
}
导出多个配置对象
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production' ? '/' : '/'
},
plugins: [],
resolve: {
alias: {
'@': resolve('src'),
}
},
module: {
rules: [
{
test: /\.json$/,
use: 'json-loader'
},
]
}
导出一个promise
webpack将运行有配置文件导出的函数,并且等到promise返回,便于需要一部加载所需的配置变量,貌似这种方式很少见。 我见的比较多是前两种方式
module.exports = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
entry: './app.js',
/* ... */
})
}, 5000)
})
}
entry和context
context
Webpack 在寻找相对路径的文件时会以context
为根目录,context
默认为执行启动 Webpack 时所在的当前工作目录。
context: path.resolve(__dirname, 'app')
entry
entry: string | [string]
object {
(function: () => string | [string] | object {
// string
entry: 'src/main.js',
// object
entry: {
main1: "src/main1.js",
main2: "src/main2.js",
}
// function ,反正这种写法我没见过
entry: () => new Promise((resolve) => resolve(['src/main1.js', './main2.js']))
output
path: 输入目录的路径,该路径是一个绝对路径
path: path.resolve(__dirname, 'dist')
publicPath: 如果是生产环境,将资源托管到CDN上去,这里的地址是demo
publicPath: process.env.NODE_ENV === 'production' ? '/demo' : '/',
filename: 输出文件的名称,这里的[name]
可以看做是多个chunk的输出
filename: '[name].js',
chunkFilename: chunk的文件名称
[id].chunk.js
sourceMapFilename: 此选项会向硬盘写入一个输出文件,只在 devtool 启用了 SourceMap 选项时才使用
sourceMapFilename: '[file].map'
完整的Output的配置,最常用的应该是前面三项
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: process.env.NODE_ENV === 'production' ? '/demo' : '/',
filename: '[name].js',
chunkFilename: '[id].chunk.js',
sourceMapFilename: '[file].map',
}
module
babel-loader
用来将Es6/Jsx转化为ES5,例子是JSX转化Es5
module: {
rules:
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015', 'react']
}
}
}
},
CSS-loader
{
test: /\.css$/,
// 排除node_modules下面的文件
exclude: /node_modules/,
// 处理的顺序从后到前,即先交个css-loader,再交给style-loader
use: ['style-loader', 'css-loader']
}
Image loader
{
test: /\.(jpg|png|gif|svg)$/,
//可以对图片进行大小限制
loader: "url-loader?limit=10000
}
reslove
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
pulgin
CommonsChunkPlugin
该插件的作用来用来提取第三方库和公共模块,避免首屏加载的bundle文件或者按需加载的bundle体积过大,从而导致加载时间过长
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
module.exports = {
plugins: [
new CommonsChunkPlugin({
name: 'polyfills',
chunks: ['polyfills']
})
}
UglifyJs Plugin
该插件的功能是压缩的js代码
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
plugins: [
new UglifyJsPlugin()
]
}
html-webpack-plugin
该插件的作用是生成html文件
const HtmlwebpackPlugin = require('html-webpack-plugin');
module.exports = {
new HtmlwebpackPlugin({
title: '',
filename: 'index.html'
}),
}
设置全局变量
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
]
}
devServer
devServer: {
port: METADATA.port,
host: METADATA.host,
hot: METADATA.HMR,
public: METADATA.PUBLIC,
historyApiFallback: true,
watchOptions: {
},
setup: function(app) {
},
performance
配置性能提示的显示方式。例如,如果您的资产超过250kb,webpack将发出警告通知您。
performance: {
hints:
process.env.NODE_ENV === 'production' &&
!process.env.VUE_APP_TEST &&
'warning',
},
其他
vue-cli3.×搭建的项目就配置一个vue.congfig.js'的文件,简化很多了设置,
具体可以看看我的配置
Vue-Cli 3.0从0 开始搭建项目篇1
更多vue-cli3.x相关知识
// 用来加载svg格式的文件
chainWebpack: config => {
const svgRule = config.module.rule('svg')
svgRule
.use('vue-svg-loader')
.loader('vue-svg-loader')
},
参考链接
阮一峰webpack-demos
webpack中文网
深入浅出webpack