一.webpack打包基本原理
1.以入口文件单个模块为例
1.1获取模块内容
使用node.js的核心模块fs
// bundle.js
const fs = require('fs')
const getModuleInfo = file => {
const body = fs.readFileSync(file, 'utf-8')
console.log(body)
}
getModuleInfo('./src/index.js')
读出来的是字符串,可以用正则表达式提取import、export的内容以及路径名。
1.2分析模块内容
安装@babel/parser,把js文件的代码内容转换成js对象的形式,抽象语法树
1.3对模块内容做处理
遍历抽象语法树,将相对路径转为绝对路径;将ES6转化ES5
2.递归获取所有模块的信息
从入口模块开始,对每一个模块以及模块依赖的模块都调用getModuleInfo 进行分析,最终返回包含所有模块信息的对象
根据模块分析数据,生产浏览器运行的代码
手写loader
loader本质上是一个函数,会在我们加载一些文件时执行。
1.创建syncLoader.js
这个函数必须返回一个buffer或string
对于loader的编写,一定不要使用箭头函数,那样会改变this的指向。
// syncLoader.js
const loaderUtils = require('loader-utils')
module.exports = function (source) {
const options = loaderUtils.getOptions(this)
console.log(options)
source += options.message
// 可以传递更详细的信息
this.callback(null, source)
}
2.配置webpack
const path = require('path')
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
resolveLoader: {
// loader路径查找顺序从左往右
modules: ['node_modules', './']
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'syncLoader',
options: {
message: '1111'
}
}
}
]
}
}
异步loader
const loaderUtils = require('loader-utils')
module.exports = function (source) {
const options = loaderUtils.getOptions(this)
const asyncfunc = this.async()
setTimeout(() => {
source += '走上人生颠覆'
asyncfunc(null, res)
}, 200)
}