美文网首页
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