astexplorer.net/ AST 可以做什么? (Babel\LESS、Eslint、Typescript) regex101.com/ 正则表达式
流程图
直接写代码
代码
webpack
fc_webpack.js
fc_webpack.js 源码
const fs = require('fs');
const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default;
const babel = require('@babel/core');
const path = require('path')
let ID=0;
function createAsset(filename){
const content = fs.readFileSync(filename,'utf-8');
const ast = parser.parse(content,{
sourceType:'module'
})
const dependencies=[]
traverse(ast,{
ImportDeclaration:({node}) =>{
dependencies.push(node.source.value);
}
})
const { code} = babel.transformFromAstSync(ast,null,{
presets:['@babel/preset-env']
})
let id=ID++;
return {
filename,
code,
dependencies,
id
}
}
function createGraph(entry){
const mainAsset = createAsset(entry);
const queue=[mainAsset];
for(const asset of queue){
const dirname = path.dirname(asset.filename);
asset.mapping={};
asset.dependencies.forEach((relativePath)=>{
const absolutePath = path.join(dirname,relativePath);
const child = createAsset(absolutePath);
asset.mapping[relativePath] =child.id;
queue.push(child)
})
}
return queue;
}
function bundle(graph){
let modules ='';
graph.forEach((mod)=>{
modules+=`
${mod.id}:[
function(require,module,exports){
${mod.code}
},
${JSON.stringify(mod.mapping)}
],
`
})
const result = `
(
function(modules){
function require(id){
const [ fn,mapping]=modules[id]
function localRequire(relativePath){
return require(mapping[relativePath])
}
const module={
exports:{}
}
fn(localRequire,module,module.exports);
return module.exports;
}
require(0);
}
)({${modules}})
`
return result;
}
const graph = createGraph('./src/index.js');
const result = bundle(graph);
console.log(result);
打包后的代码
;(function (modules) {
function require(id) {
const [fn, mapping] = modules[id]
function localRequire(relativePath) {
return require(mapping[relativePath])
}
const module = {
exports: {},
}
fn(localRequire, module, module.exports)
return module.exports
}
require(0)
})({
0: [
function (require, module, exports) {
'use strict'
var _info = _interopRequireDefault(require('./info.js'))
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { default: obj }
}
console.log(_info['default'])
},
{ './info.js': 1 },
],
1: [
function (require, module, exports) {
'use strict'
Object.defineProperty(exports, '__esModule', {
value: true,
})
exports['default'] = void 0
var _consts = require('./consts.js')
var _default = (exports['default'] = '\u6B22\u8FCE\u6765\u5230 '.concat(
_consts.company,
))
},
{ './consts.js': 2 },
],
2: [
function (require, module, exports) {
'use strict'
Object.defineProperty(exports, '__esModule', {
value: true,
})
exports.company = void 0
var company = (exports.company = '\u9605\u6587')
},
{},
],
})