sourceMap: devtool 模式以及SourceMapDevToolPlugin的使用

1.  什么是sourceMap

sourceMap 是一个信息文件, 维护着代码转换编译前后的映射关系;

2. devtool : 选项控制是否生成,以及如何生成 source map source Map对应的模式 

1)inline

2) cheap

3)module

4) eval

5) source-map

3-21 加载 Source Map · 深入浅出 Webpack

然后根据上述几种 进行组合 验证 devtool 名称时, 我们期望使用某种模式, 注意不要混淆 devtool 字符串的顺序, 模式是: [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map.

见图: 

sourceMap: devtool 模式以及SourceMapDevToolPlugin的使用_第1张图片

 

 

如果是eval / inline 模式 不会生成单独.map 文件, 会以dataUrl 的形式 存在打包文件后的结尾

source-map 会生成单独的.map 文件 

3 . 浏览器中的表现形式

如果加载的js 的文件 结尾有#sourceMap(eval) 或者 #sourceMapUrl(source-map)(比如如果是hidden-source-map 这种打包出来的js 文件 就没有 ,所以不会自动关联), 可以右键 选择 添加源映射

解析到#sourceMap 或者 #sourceMapUrl 的时候 会自动去关联到(hidden-xxx 的除外)

4. 使用了压缩插件 uglifyjs-webpack-plugin或者terser-webpack-plugin 如果想使用source-map 如果再设置下sourceMap: true, 因为压缩插件里面 默认 sourceMap: false

chainWebpack(config) {
    config
      .devtool('hidden-source-map')
      .end()
    config
      .when(process.env.NODE_ENV === 'production',
        config => {
          config.optimization.minimizer('js').use(
            new uglifyjs({
              sourceMap: true
              uglifyOptions: {
                warnings: false,
                compress: {
                  drop_console: true,
                  drop_debugger: true,
                  pure_funcs: ['console.log', 'console.warn']
                }
              }
            })
          )
        })
  }

5.  生产环境下一般使用source-map 或者 hidden-source-map 模式  , 具体可以参考官网推荐, 生成的map 文件 不要和业务代码部署到一起, 防止被别人看到, 可以单独进行部署,实现私有化, 只能特定网络下访问, 比如部署到公司内网服务器, 此时就要修改js 文件结尾的#sourceMapUrl 链接地址 

//# sourceMappingURL=app.fea6fcf0.js.map 修改为

//# sourceMappingURL=http: xxxxx:xxxx/app.fea6fcf0.js.map 

6. 插件 : 实现了对 source map 生成内容进行更细粒度的控制

 | webpack 中文文档

你可以直接使用 SourceMapDevToolPlugin/EvalSourceMapDevToolPlugin 来替代使用 devtool 选项,因为它有更多的选项。切勿同时使用 devtool 选项和 SourceMapDevToolPlugin/EvalSourceMapDevToolPlugin 插件devtool 选项在内部添加过这些插件,所以你最终将应用两次插件。

比如我们要单独部署.map 文件 需要修改map链接的地址, 可以设置这个时候publicPath或者 append 就可以使用插件:

const webpack = require('webpack')
module.exports = {
  productionSourceMap: true,
  chainWebpack(config) {
    config.plugin('SourceMapDevToolPlugin')
      .use(webpack.SourceMapDevToolPlugin).tap(args => {
        return [{
          filename: '[file].map',
          publicPath: 'https://exmaple.com/',
// append: "\n//# sourceMappingURL=http://example.com/sourcemap/[url]",
          moduleFilenameTemplate: 'source-map'
        }]
      })
  }
}

上述代码打包之后 发现 js文件 结尾会有两个#sourceMapUrl

{return l&&h.REQUIRED&&d(e)&&!n(e,c)&&p(e),e},h=e.exports={REQUIRED:!1,fastKey:f,getWeakData:m,onFreeze:b};i[c]=!0}}]);
//# sourceMappingURL=https://exmaple.com/static/js/chunk-540c250b.99bc351b.js.map
//# sourceMappingURL=chunk-540c250b.99bc351b.js.map

这个就说明 vue-cli4(目前我使用的版本) 中使用了 devtool ,devtool 和SourceMapDevToolPlugin 插件同时存在,所以导致了两个sourceMap指向, SourceMapDevToolPlugin插件是用来替代devtool,看源码会发现  cli中有多处会根据 productionSourceMap这个布尔值来设置是否使用 devtool ;需要注意的是vue-cli4默认的js 压缩插件 是 terser-webpack-plugin, 如果想生成sourceMap 压缩插件这个属性必须设置true

两处源码如下:

sourceMap: devtool 模式以及SourceMapDevToolPlugin的使用_第2张图片

sourceMap: devtool 模式以及SourceMapDevToolPlugin的使用_第3张图片

可能你会想直接设置productionSourceMap为false, 这个时候 就会导致 terser-webpack-plugin 插件sourceMap 也会为false, map文件就生成不了, 我们的目标是生成map文件 , 同时去掉自带的devtool 保留SourceMapDevToolPlugin插件

所以第一种就是设置productionSourceMap为true, 同时在chainWebpack手动设置devtool:false, 覆盖自带的devtool,

const webpack = require('webpack')
module.exports = {
  productionSourceMap: true,
  chainWebpack(config) {
    config.devtool(false).end()
    config.plugin('SourceMapDevToolPlugin')
      .use(webpack.SourceMapDevToolPlugin).tap(args => {
        return [{
          filename: '[file].map',
          publicPath: 'https://exmaple.com/',
          moduleFilenameTemplate: 'source-map'
        }]
      })
  }
}

第二种就是 设置productionSourceMap:false 同时设置压缩插件的sourceMap: true (但是这种不能保证其他插件需不需要设置 ) 所以最好还是选择第一种吧

const webpack = require('webpack')
const terser = require('terser-webpack-plugin')
module.exports = {
  productionSourceMap: false,
  chainWebpack(config) {
    config.plugin('SourceMapDevToolPlugin')
      .use(webpack.SourceMapDevToolPlugin).tap(args => {
        return [{
          filename: '[file].map',
          publicPath: 'https://exmaple.com/',
          moduleFilenameTemplate: 'source-map'
        }]
      })
// vue-cli4 这种方式生效
    config.optimization.minimizer('terser').tap((args) => {
      args[0].sourceMap = true
      return args
    })
  }
}

 

同样css 也有sourceMap, vue-cli3 默认是关闭的

css: {

    sourceMap: true

  },

参考:

Devtool | webpack 中文文档

何为SourceMap?讲讲SourceMap食用姿势 - 知乎

https://www.jianshu.com/p/721b0d26e1ea

Webpack devtool source map « Cheng's Blog

Source Maps

深入浅出的webpack构建工具---devTool中SourceMap模式详解(四) - 龙恩0707 - 博客园

Webpack 实战系列一:正确使用 Sourcemap-51CTO.COM

webpack - vue-cli sourcemap私有化部署配置_个人文章 - SegmentFault 思否

 

 

 

 

你可能感兴趣的:(javascript,前端,开发语言,webpack)