网站:canIuse
常用loader--补loader的原理
style-loader css-loader less-loader (sass-loader stylus-loader)postcss-loader (autoprefixer插件 、package.json里 browserslist、cssnano)
plugins
mini-css-extrace-plugins
原理解析
1、解析入口文件
读取入口文件内容,转AST语法树,获取import 节点获取依赖文件
将AST语法树 转成code
递归或者循环依赖文件内容的依赖
形成依赖图谱
2、处理require 以及 exports 方法
简单例子:
const fs = require("fs");
const path = require("path");
const parse = require("@babel/parser");
const { transformFromAst } = require('@babel/core');
const traverse = require("@babel/traverse").default;
module.exports = class webpack {
constructor(option) {
console.log(option);
const { entry, output } = option;
this.entry = entry;
this.output = output;
this.modules = [];
}
run() {
const info = this.parse(this.entry);
this.modules.push(info);
for (let i = 0; i < this.modules.length; i++) {
const item = this.modules[i];
const { yilai } = item;
if (yilai)
for (let j in yilai) {
this.modules.push(this.parse(yilai[j]))
}
}
// 数据接口转换
const obj = {};
this.modules.forEach(item => {
obj[item.entryFile] = {
yilai: item.yilai,
code: item.code
}
})
console.log(obj)
this.file(obj)
}
parse(entryFile) {
const content = fs.readFileSync(entryFile, "utf-8");
const ast = parse.parse(content, { sourceType: 'module' })
const dirname = path.dirname(entryFile);
// 分析依赖 以及依赖的路径
const yilai = {};
traverse(ast, {
ImportDeclaration({ node }) {
const newPath = './' + path.join(dirname, node.source.value);
yilai[node.source.value] = newPath;
}
})
const { code } = transformFromAst(ast, null, {
presets: ['@babel/preset-env']
})
return {
entryFile,
yilai,
code
}
}
file(code) {
// 生成文件,放入dist目录
const filePath = path.join(this.output.path, this.output.filename)
//生成bundle文件内容
//webpackBootstrap
const newcode = JSON.stringify(code);
const bundle = `(function(modules){
function require(module) {
function pathRequire(relativePath) {
//相对入口文件路径-》相对项目路径
console.log(require)
return require(modules[module].yilai[relativePath])
}
const exports = {};
(function(require,exports,code){
eval(code)
})(pathRequire,exports,modules[module].code)
return exports;
}
require('${this.entry}')
})(${newcode})`
fs.mkdir(this.output.path, () => {
})
fs.writeFileSync(filePath, bundle, 'utf-8')
console.log(filePath)
}
}