美文网首页
webpack学习(三)简单实现webpack

webpack学习(三)简单实现webpack

作者: 起飞之路 | 来源:发表于2019-09-26 18:57 被阅读0次

简单实现

要实现一个简单的webpack,我们首先要理解其中的原理,目前还没看过源码,现在的理解是通过对入口文件分析,转成抽象语法树,进而可以深度遍历到所有依赖的文件,然后将文件转码成我们想要的文件,

我们先来写一下我们想打包的文件

// index.js
import util from './util/util.js';
console.log(util.add(1, 2));

// util.js
function add(a, b) {
  return a + b;
}
export default {
  add,
};

首先我们先从分析入口文件开始,了解一下文件是怎样被分析转成抽象语法树的,编译过程前端为词法分析,语法分析,生成抽象语法树,我们来读取字符串来匹配还是很麻烦的,babel给我们提供了现成的方法,我们先来安装我们需要的几个babel的包@babel/parser @babel/traverse @babel/core @babel/preset-env,我们使用parser来解析代码生成抽象语法树,traverse遍历取出抽象语法树中我们想要的信息,另外两个包我们使用过,帮我们来生成低版本浏览器可以使用的代码

const fs = require('fs');
const path = require('path');
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const babel = require('@babel/core');

function analysisEntry(filename) {
  let content = fs.readFileSync(filename, 'utf-8');
  const ast = parser.parse(content, {
    sourceType: 'module',
  });
  const dependencies = {};
  traverse(ast, {
    ImportDeclaration({ node }) {
      const dirname = path.dirname(filename);
      dependencies[node.source.value] = './' + path.join(dirname, node.source.value);
    },
  });
  const code = babel.transformFromAst(ast, null, {
    presets: ['@babel/preset-env'],
  }).code;
  return {
    filename,
    dependencies,
    code,
  };
}

通过上边的方法我们可以对入口文件分析,剩下的就是,对所有依赖文件进行分析然后生成代码了,我们通过深度遍历,把每一个依赖的文件加入到一个对象中,最后定义一个require方法来加载我们的code

function dependenciesGraph(entry) {
  const root = analysisEntry(entry);
  const graphArray = [root];
  let i = 0;
  const graph = {};
  while (i < graphArray.length) {
    let item = graphArray[i];
    for (const key in item.dependencies) {
      const element = item.dependencies[key];
      graphArray.push(analysisEntry(element));
    }
    i++;
  }
  graphArray.forEach(i => {
    graph[i.filename] = i;
  });
  return graph;
}

function generateCode(entry) {
  const graph = JSON.stringify(dependenciesGraph(entry))
  return `(function(graph){
    function require(module){
      function localRequire(path) {
        return require(graph[module].dependencies[path])
      }
      var exports = {};
      (function(require, exports, code){
        eval(code)
      })(localRequire, exports, graph[module].code)
      return exports;
    }
    require('${entry}')
  })(${graph})`
}

console.log(generateCode('./src/index.js'))

相关文章

网友评论

      本文标题:webpack学习(三)简单实现webpack

      本文链接:https://www.haomeiwen.com/subject/dxunuctx.html