webpack进阶之路

稀里糊涂的module、chunk、bundle

开局一张图

图作者为水印上的人(侵删,谢谢)

  • 我们写的文件就是一个个的module,当这些module到达webpack进行打包的时候,webpack会根据各个文件之间的引用关系生成chunk,而webpack处理好chunk之后就会输出bundlebundle是经过加载和编译之后的最终源文件,可以直接在浏览器中运行的

  • 一般来说一个chunk对应一个bundle,当然也有一个chunk对应几个bundle

  • 总结: module|chunk|bundle是同一份逻辑代码在不同场景下的名字

    • 我们直接写出来的是module
    • webpack处理的时是chunk
    • 浏览器运行的是bundle

filename和chunkFilename的区别

filename

  • filename是输入文件经过webpack编译之后输出的文件的文件名

chunkFilename

  • 是指未在entry中列出来,却又需要被打包出来的chunk文件的名称(如懒加载)
  • 如果不做任何配置,打包出来的文件名是:[id].js(这个id是指webpack打包时候的chunk的id)
  • 如果在output内指定chunkFilename,打包出来就是对应的名称

总结

  • filename是列在entry里打包的文件对应的名称
  • chunkFilename是未列在entry里但需要打包的文件的名称

webpackPrefetch、webpackPreload和webpackChunkName

  • 这几个都是webpack魔法注释中常用的三个

webpackChunkName

  • webpackChunkName: 按照上面chunkFilename的写法在多个异步加载文件的时候都是一个名字

    1
    2
    3
    4
    output: {
    filename: [name].js,
    chunkFilename: bundle.js
    }
  • 如果我们加上一个变量

    1
    2
    3
    4
    output: {
    filename: [name].js,
    chunkFilename: [name].bundle.js // 打包出来是:1.bundle.js ,因为chunk的id是1,辨识度低
    }
  • 这个时候就需要用到webpackChunkName了

    1
    2
    // 在 import 的括号里 加注释 /* webpackChunkName: "lodash" */ ,为引入的文件取别名
    const { default: _ } = await import(/* webpackChunkName: "lodash" */ 'lodash');
  • 打包出来的文件名就是vendors~lodash.bundle.js,为什么有vendors~呢? 因为webpack内部懒加载有一个插件叫SplitChunksPlugin,里面有一些配置比如automaticNameDelimiter默认分割符就是~

webpackPrefetch

  • webpackPrefetch:预拉取

    • 普通的异步加载:在头部增加一个script标签

      1
      2
      3
      4
      5
      6
      7
      // 异步加载
      async function getLodash() {
      const element = document.createElement('div');
      const { default: _ } = await import('lodash');
      element.innerHTML = _.join(['Hello!', 'Joye', '~'], ' ');
      return element;
      }
    • 加了webpackPrefetch的异步加载: