webpack打包器

51 阅读1分钟

简单webpack打包器

//  webpack 打包器
const fs = require('fs')
const path = require('path')
const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default
const babel = require('@babel/core')

// 入口出口文件
const config = {
    entry : './entry.js',
    output : './dist.js'
}

// 处理文件
function readFile(entry){
    let fileUrl = './' + path.relative(__dirname,entry).replace('\\','/');
    fileUrl += path.extname(fileUrl) ? "" : '.js'
    const content = fs.readFileSync(fileUrl,'utf-8');
    const deps = [];
    // 将js文件转化成ast
    const ast = parser.parse(content);
    // 对ast文件进行处理
    traverse(ast,{
        CallExpression:({node})=>{
          if(node.callee.name === 'require'){
            node.callee.name = '__webpack__require__';
            let url = node.arguments[0].value;
            url += path.extname(node.arguments[0].value) ? '' : '.js';
            url = './' + path.relative(__dirname,url).replace('\\','/');
            deps.push(url)
          }
        }
    })
    const { code } = babel.transformFromAstSync(ast)
    return {
        fileUrl,
        deps,
        code
    }
}
function start({
    entry,
    output
}){
  // 递归找 所有文件并进行文件处理
  const entryInfo = readFile(entry);
  const list = [entryInfo]
  for(let prop of list){
    prop.deps.forEach(item=>{
        list.push(readFile(item))
    })
  }
  fs.writeFileSync(output,build(list,entry))
}
// 打包
function build(list,entry){
   return `(()=>{var webpackModule = {
      ${
        list.map(item=>{
           return `
            '${item.fileUrl}' : (module, exports, __webpack__require__ )=>{ eval(\`${item.code}\`) }
           `
        }).join(',')
      }
   }
   const cache = {}
   function __webpack__require__(moduleId){
        if(cache[moduleId]){
            return cache[moduleId].exports
        }
        var module = cache[moduleId] ={
            exports : {}
        }
        webpackModule[moduleId](module,module.exports,__webpack__require__)
        return cache[moduleId].exports
   }
   __webpack__require__('${entry}');
})()`
}

start(config)

打包的结果

(()=>{var webpackModule = {
      
            './entry.js' : (module, exports, __webpack__require__ )=>{ eval(`const a = __webpack__require__('./a.js');
console.log('a', a);`) }
           ,
            './a.js' : (module, exports, __webpack__require__ )=>{ eval(`const b = __webpack__require__('./src/b.js');
const a = 6666;
console.log('b', b);
module.exports = a;`) }
           ,
            './src/b.js' : (module, exports, __webpack__require__ )=>{ eval(`module.exports = 555;`) }
           
   }
   const cache = {}
   function __webpack__require__(moduleId){
        if(cache[moduleId]){
            return cache[moduleId].exports
        }
        var module = cache[moduleId] ={
            exports : {}
        }
        webpackModule[moduleId](module,module.exports,__webpack__require__)
        return cache[moduleId].exports
   }
   __webpack__require__('./entry.js');
})()

目录结构

image.png