webpack运行流程
webpack启动后会从 Entry 里配置的 Module 开始递归解析 Entry 依赖的所有Module.每找到一个Module,就会根据配置的Loader去找出对应的转换规则,
对Module进行转换后,再解析出当前的Module依赖的Module.这些模块会以Entry为单位进行分组,一个Entry和其所有依赖的Module被分到一个组也就是一个
Chunk。最后Webpack会把所有Chunk转换成文件输出。在整个流程中Webpack会在恰当的时机执行Plugin里定义的逻辑。
- Entry:入口,webpack执行构建的第一步从Entry开始,可以抽象成输入。
- module:模块,在webpack中一切皆模块,一个模块对应着一个文件,webpack会从配置的Entry开始递归找出所有依赖的模块。
- loader:模块转换器,用于把模块原内容按照需求转换成新内容
- plugin:扩展插件,在webpack构建流程中的特定时机注入扩展逻辑来改变构建结果或做你想要做的事情
- Chunk:代码库,一个chunk由十多个模块组合而成,用于代码合并与分割
- Output:输出结果
vue-cli 2.X webpack 模板配置注释
// 此文件为通过vue-cli 拉取的webpack 模板
// 文件路径:build\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 = {
context: path.resolve(__dirname, '../'), // webpack在寻找相对路径的文件时会以context为根目录,context默认为执行启动webpack时所在的当前工作目录
entry: {
app: './src/main.js' // 配置多个入口,每个入口生成一个Chunk。如果entry是一个object,就可能出现多个chunk,这时chunk的名称是object键值对里键的名称。
},
output: {
path: config.build.assetsRoot, // 输出文件路径 默认值为:assetsRoot: path.resolve(__dirname, '../dist')
filename: '[name].js', // 代码里的[name]代表用内置的name变量去替换[name],这时你可以把它看做一个字符串模板函数,每个要输出的chunk都会通过这个函数去拼接出输出的文件名称。
publicPath: process.env.NODE_ENV === 'production' // 在项目中可能会有一些构建出的资源需要异步加载,加载这些异步资源需要对应的URL地址。
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: { // Webpack 在启动后会从配置的入口模块出发找出所有依赖的模块,Resolve 配置 Webpack 如何寻找模块所对应的文件。 Webpack 内置 JavaScript 模块化语法解析功能,默认会采用模块化标准里约定好的规则去寻找,但你也可以根据自己的需要修改默认的规则。
extensions: ['.js', '.vue', '.json'],
alias: { // 配置项通过别名来把原导入路径映射成一个新的导入路径
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'), // 把路径中的@替换成src 当你通过 import Button from '@/components/button 导入时,实际上被 alias 等价替换成了 import Button from './src/components/button' 。
}
},
module: { // module的配置如何处理模块。
rules: [ // rules 配置模块的读取和解析规则, 通常用来配置loader, 其类型是一个数组, 数组里每一项都描述了如何去处理部分文件。
{
test: /\.vue$/, // 条件匹配: 通过test、include、exclude三个配置来命中Loader要应用的规则文件。
loader: 'vue-loader', // 指定loader解析
// 在loader需要传入很多参数的时候,我们还可以通过一个object来描述,如:
// use: [
// {
// loader: 'babel-loader',
// options: {
// cacheDirectory: true
// },
// // enforce:'post' 的含义是把该 Loader 的执行顺序放到最后
// // enforce 的值还可以是 pre,代表把 Loader 的执行顺序放到最前面
// enforce:'post'
// }
// ]
options: vueLoaderConfig // vue的配置
},
{
test: /.md$/,
loader: 'text-loader',
include: [
path.resolve(__dirname, 'src'), // 指定需要处理文件的位置
path.resolve(__dirname, 'test')
],
exclude: [
path.resolve(__dirname, 'node_modules'), // 指定不需要处理的位置
path.resolve(__dirname, 'bower_modules')
]
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [
resolve('src'),
resolve('test'),
resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000, // 10kb以下的图片转换成base64
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000, // 10kb以下的音频视频转换成base64
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000, // 10kb以下的字体文件转换成base64
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}