webpack devtools_webpack loader和plugin的区别

2022-11-08 15:16:49 浏览数 (1)

首先我们需要知道source map是什么?顾名思义资源映射,它做的就是维护打包处理后的代码与源代码之间的映射关系,只有映射的精确性则取决于webpack的配置项devtool,其决定了项目打包时是否以及如何生成source map,而生成的source map不同决定了构建产物的体积构建以及重新构建的速度的不同。具体配置项可选值可参考webpack文档这里不一一列举。

首先可以看一下webpack的源码,对应处理逻辑仅有20行:https://github.com/webpack/webpack/blob/226a77c9d46b33da5b78b1c76a10384c78132074/lib/WebpackOptionsApply.js#L188

代码语言:javascript复制
if (options.devtool) {
    if (options.devtool.includes("source-map")) {
        const hidden = options.devtool.includes("hidden");
        const inline = options.devtool.includes("inline");
        const evalWrapped = options.devtool.includes("eval");
        const cheap = options.devtool.includes("cheap");
        const moduleMaps = options.devtool.includes("module");
        const noSources = options.devtool.includes("nosources");
        const Plugin = evalWrapped
            ? require("./EvalSourceMapDevToolPlugin")
            : require("./SourceMapDevToolPlugin");
        new Plugin({
            filename: inline ? null : options.output.sourceMapFilename,
            moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,
            fallbackModuleFilenameTemplate:
                options.output.devtoolFallbackModuleFilenameTemplate,
            append: hidden ? false : undefined,
            module: moduleMaps ? true : cheap ? false : true,
            columns: cheap ? false : true,
            noSources: noSources,
            namespace: options.output.devtoolNamespace
        }).apply(compiler);
    } else if (options.devtool.includes("eval")) {
        const EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin");
        new EvalDevToolModulePlugin({
            moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,
            namespace: options.output.devtoolNamespace
        }).apply(compiler);
    }
}

从上述代码可看出,会首先判断devtool的值是否包含source-map或者eval(注意是包含判断,并不是相等判断),也就是说只要不包含两者之一,其实是什么值都无所谓,结果都一样。由此针对devtool的不同配置项,可做这样的拆分处理:

任何不包含source-map或者eval

浏览器中不会有任何代码映射关系可寻,只能定位到打包后代码的位置。

不包含source-map且包含eval:

会将打包后每个模块的代码使用 eval() 执行,且在模块最后注释有sourceURL=xxx/xx/xx/xx.js.map类似路径,用于定位,能够定位到源码文件路径,但是代码为build后生成的代码。具体逻辑可以看这里:传送门

包含source-map:

包含source-map决定了将以更为细粒度的方式来展示代码映射的详情。

其中有根据是否包含额外字段做了不同处理:

  • eval: build后的模块代码是否使用eval执行
  • hidden: 是否不需要在模块末尾追加source map url(sourceMappingURL), 决定了是否可以定位到build之前的源码文件,该字段存在的话只能定位到build以后的chunk文件中对应模块及所在行。
  • inline: 是否使用options.output.sourceMapFilename作为source map文件的名称比如://# sourceMappingURL=main.chunk.js.map,包含该字段则sourceMappingURL值直接为base64数据,不包含则为对应map文件名称。
  • module: 包含 loader 直接转换的 sourcemap(比如 jsx to js ,babel 的 sourcemap),否则无法定义源文件
  • cheap: 该字段影响两个地方,一个当不包含module字段且不包含cheap时与包含module控制功能生效;另一个是决定了定位时是否映射定位到对应列,包含则不映射定位。
  • nosources: 该字段存在则意味着map文件中不存在对应源码内容

devtool的处理代码中可以看出,实际是根据配置项依赖EvalDevToolModulePlugin或者SourceMapDevToolPlugin插件生成source map的,因此,可以通过将devtool设置成false,然后在webpack.plugins中通过自定义的配置来完成对应工作,来达到更为细致的控制。 比如可以通过exclude字段来排除一些不需要生成source map的模块:

代码语言:javascript复制
devtool: false, 
plugins: [ 
    new webpack.EvalSourceMapDevToolPlugin({ 
      exclude: /node_modules/, 
      module: true, 
      columns: false 
    }) 
],

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/185426.html原文链接:https://javaforall.cn

0 人点赞