webpack

网站:canIuse

常用loader--补loader的原理

style-loader css-loader less-loader (sass-loader stylus-loader)postcss-loader (autoprefixer插件 、package.json里 browserslist、cssnano)

plugins

mini-css-extrace-plugins

原理解析

1、解析入口文件

读取入口文件内容,转AST语法树,获取import 节点获取依赖文件

将AST语法树 转成code

递归或者循环依赖文件内容的依赖

形成依赖图谱

2、处理require 以及 exports 方法

简单例子:


const fs = require("fs");

const path = require("path");

const parse = require("@babel/parser");

const { transformFromAst } = require('@babel/core');

const traverse = require("@babel/traverse").default;

module.exports = class webpack {

  constructor(option) {

    console.log(option);

    const { entry, output } = option;

    this.entry = entry;

    this.output = output;

    this.modules = [];

  }

  run() {

    const info = this.parse(this.entry);

    this.modules.push(info);

    for (let i = 0; i < this.modules.length; i++) {

      const item = this.modules[i];

      const { yilai } = item;

      if (yilai)

        for (let j in yilai) {

          this.modules.push(this.parse(yilai[j]))

        }

    }

    // 数据接口转换

    const obj = {};

    this.modules.forEach(item => {

      obj[item.entryFile] = {

        yilai: item.yilai,

        code: item.code

      }

    })

    console.log(obj)

    this.file(obj)

  }

  parse(entryFile) {

    const content = fs.readFileSync(entryFile, "utf-8");

    const ast = parse.parse(content, { sourceType: 'module' })

    const dirname = path.dirname(entryFile);

    // 分析依赖 以及依赖的路径

    const yilai = {};

    traverse(ast, {

      ImportDeclaration({ node }) {

        const newPath = './' + path.join(dirname, node.source.value);

        yilai[node.source.value] = newPath;

      }

    })

    const { code } = transformFromAst(ast, null, {

      presets: ['@babel/preset-env']

    })

    return {

      entryFile,

      yilai,

      code

    }

  }

  file(code) {

    // 生成文件,放入dist目录

    const filePath = path.join(this.output.path, this.output.filename)

    //生成bundle文件内容

    //webpackBootstrap

    const newcode = JSON.stringify(code);

    const bundle = `(function(modules){

      function require(module) {

        function pathRequire(relativePath) {

          //相对入口文件路径-》相对项目路径

          console.log(require)

        return  require(modules[module].yilai[relativePath])

        }

        const exports = {};

        (function(require,exports,code){

          eval(code)

        })(pathRequire,exports,modules[module].code)

        return exports;

      }

      require('${this.entry}')

    })(${newcode})`

    fs.mkdir(this.output.path, () => {

    })

    fs.writeFileSync(filePath, bundle, 'utf-8')

    console.log(filePath)

  }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。