webpack原理-实现webpack打包js

// 这里导入webpack配置,我用对象的形式表示,当然entry属性上定义的文件要有
// const config = require("./webpack.config");
const config = { entry: './src/index.js' };

const { join, dirname } = require("path");
const { readFileSync, writeFileSync } = require("fs");
const reg = /(?<=from\s+['"])[\.\/\w]+(?=['"])/g;

class Complier {
  constructor({ entry }) {
    this.entry = entry;
  }
  run() {
    writeFileSync('generateFile.js', generateCode(this.entry));
  }
}

const parser = (entry, prePath = '.') => {
    let temp = null;
    const filePath = `./${join(prePath, entry)}`;
    const code = Buffer.from(readFileSync(filePath)).toString();
    const dependencies = {};
    // 通过正则将当前文件es导入的模块识别并存到dependencies里,注释也会存起来,请不要写注释
    while ((temp = reg.exec(code)) !== null) {
      temp.forEach(filePath => {
        dependencies[filePath] = `./${join(prePath, dirname(entry), filePath)}`;
      })
    }
    
    return {
      filePath,
      dependencies,
      code,
    };
  }

const makeDependenciesGraph = (entry) => {
  const entryModule = parser(entry);
  const graphArray = [entryModule];
  // 利用广度遍历的思想遍历一遍
  for (let i = 0; i < graphArray.length; i++) {
    const { dependencies } = graphArray[i];
    if (dependencies) {
      for (let path in dependencies) {
        graphArray.push(parser(path, dirname(entry)));
      }
    }
  }
  const graph = {};
  graphArray.forEach(({ filePath, dependencies, code }) => {
    graph[filePath] = {
      dependencies,
      code
    };
  });
  return graph;
};

const generateCode = (entry) => {
  const graph = JSON.stringify(makeDependenciesGraph(entry));
  return `
  (function (graph) {
  function require(module) {
    function localRequire(relativePath) {
      return require(graph[module].dependencies[relativePath]);
    }
    var exports = {};
    (function (require, exports, code) {
      eval(code);
    })(localRequire, exports, graph[module].code);
    return exports;
  }
  require("${`./${join('.', entry).replace(/\\/g, '\\\\')}`}");
})(${graph});
 `;
};

new Complier(config).run();

posted @ 2020-11-21 11:56  代码男孩  阅读(96)  评论(0编辑  收藏  举报