导航菜单

  • 0.api
  • 0.Async
  • 0.module
  • 1.ES2015
  • 2.Promise
  • 3.Node
  • 4.NodeInstall
  • 5.REPL
  • 6.NodeCore
  • 7.module&NPM
  • 8.Encoding
  • 9.Buffer
  • 10.fs
  • 11.Stream-1
  • 11.Stream-2
  • 11.Stream-3
  • 11.Stream-4
  • 12-Network-2
  • 12.NetWork-3
  • 12.Network-1
  • 13.tcp
  • 14.http-1
  • 14.http-2
  • 15.compress
  • 16.crypto
  • 17.process
  • 18.yargs
  • 19.cache
  • 20.action
  • 21.https
  • 22.cookie
  • 23.session
  • 24.express-1
  • 24.express-2
  • 24.express-3
  • 24.express-4
  • 25.koa-1
  • 26.webpack-1-basic
  • 26.webpack-2-optimize
  • 26.webpack-3-file
  • 26.webpack-4.tapable
  • 26.webpack-5-AST
  • 26.webpack-6-sources
  • 26.webpack-7-loader
  • 26.webpack-8-plugin
  • 26.webpack-9-hand
  • 26.webpack-10-prepare
  • 28.redux
  • 28.redux-jwt-back
  • 28.redux-jwt-front
  • 29.mongodb-1
  • 29.mongodb-2
  • 29.mongodb-3
  • 29.mongodb-4
  • 29.mongodb-5
  • 29.mongodb-6
  • 30.cms-1-mysql
  • 30.cms-2-mysql
  • 30.cms-3-mysql
  • 30.cms-4-nunjucks
  • 30.cms-5-mock
  • 30.cms-6-egg
  • 30.cms-7-api
  • 30.cms-8-roadhog
  • 30.cms-9-yaml
  • 30.cms-10-umi
  • 30.cms-12-dva
  • 30.cms-13-dva-ant
  • 30.cms-14-front
  • 30.cms-15-deploy
  • 31.dva
  • 31.cms-13-dva-antdesign
  • 33.redis
  • 34.unittest
  • 35.jwt
  • 36.websocket-1
  • 36.websocket-2
  • 38.chat-api-1
  • 38.chat-api-2
  • 38.chat-3
  • 38.chat-api-3
  • 38.chat
  • 38.chat2
  • 38.chat2
  • 39.crawl-0
  • 39.crawl-1
  • 39.crawl-2
  • 40.deploy
  • 41.safe
  • 42.test
  • 43.nginx
  • 44.enzyme
  • 45.docker
  • 46.elastic
  • 47.oauth
  • 48.wxpay
  • index
  • 52.UML
  • 53.design
  • index
  • 54.linux
  • 57.ts
  • 56.react-ssr
  • 58.ts_react
  • 59.ketang
  • 59.ketang2
  • 61.1.devops-linux
  • 61.2.devops-vi
  • 61.3.devops-user
  • 61.4.devops-auth
  • 61.5.devops-shell
  • 61.6.devops-install
  • 61.7.devops-system
  • 61.8.devops-service
  • 61.9.devops-network
  • 61.10.devops-nginx
  • 61.11.devops-docker
  • 61.12.devops-jekins
  • 61.13.devops-groovy
  • 61.14.devops-php
  • 61.15.devops-java
  • 61.16.devops-node
  • 61.17.devops-k8s
  • 62.1.react-basic
  • 62.2.react-state
  • 62.3.react-high
  • 62.4.react-optimize
  • 62.5.react-hooks
  • 62.6.react-immutable
  • 62.7.react-mobx
  • 62.8.react-source
  • 63.1.redux
  • 63.2.redux-middleware
  • 63.3.redux-hooks
  • 63.4.redux-saga
  • 63.5.redux-saga-hand
  • 64.1.router
  • 64.2.router-connected
  • 65.1.typescript
  • 65.2.typescript
  • 65.3.typescript
  • 65.4.antd
  • 65.4.definition
  • 66-1.vue-base
  • 66-2.vue-component
  • 66-3.vue-cli3.0
  • 66-4.$message组件
  • 66-5.Form组件
  • 66-6.tree
  • 66-7.vue-router-apply
  • 66-8.axios-apply
  • 66-9.vuex-apply
  • 66-10.jwt-vue
  • 66-11.vue-ssr
  • 66-12.nuxt-apply
  • 66-13.pwa
  • 66-14.vue单元测试
  • 66-15.权限校验
  • 67-1-network
  • 68-2-wireshark
  • 7.npm2
  • 69-hooks
  • 70-deploy
  • 71-hmr
  • 72.deploy
  • 73.import
  • 74.mobile
  • 75.webpack-1.文件分析
  • 75.webpack-2.loader
  • 75.webpack-3.源码流程
  • 75.webpack-4.tapable
  • 75.webpack-5.prepare
  • 75.webpack-6.resolve
  • 75.webpack-7.loader
  • 75.webpack-8.module
  • 75.webpack-9.chunk
  • 75.webpack-10.asset
  • 75.webpack-11.实现
  • 76.react_optimize
  • 77.ts_ketang_back
  • 77.ts_ketang_front
  • 78.vue-domdiff
  • 79.grammar
  • 80.tree
  • 81.axios
  • 82.1.react
  • 82.2.react-high
  • 82.3.react-router
  • 82.4.redux
  • 82.5.redux_middleware
  • 82.6.connected
  • 82.7.saga
  • 82.8.dva
  • 82.8.dva-source
  • 82.9.roadhog
  • 82.10.umi
  • 82.11.antdesign
  • 82.12.ketang-front
  • 82.12.ketang-back
  • 83.upload
  • 84.graphql
  • 85.antpro
  • 86.1.uml
  • 86.2.design
  • 87.postcss
  • 88.react16-1
  • 89.nextjs
  • 90.react-test
  • 91.react-ts
  • 92.rbac
  • 93.tsnode
  • 94.1.JavaScript
  • 94.2.JavaScript
  • 94.3.MODULE
  • 94.4.EventLoop
  • 94.5.文件上传
  • 94.6.https
  • 94.7. nginx
  • 95.1. react
  • 95.2.react
  • 96.1.react16
  • 96.2.fiber
  • 96.3.fiber
  • 97.serverless
  • 98.websocket
  • 100.1.react-basic
  • 101.1.monitor
  • 101.2.monitor
  • 102.java
  • 103.1.webpack-usage
  • 103.2.webpack-bundle
  • 103.3.webpack-ast
  • 103.4.webpack-flow
  • 103.5.webpack-loader
  • 103.6.webpack-tapable
  • 103.7.webpack-plugin
  • 103.8.webpack-optimize1
  • 103.9.webpack-optimize2
  • 103.10.webpack-hand
  • 103.11.webpack-hmr
  • 103.11.webpack5
  • 103.13.splitChunks
  • 103.14.webpack-sourcemap
  • 103.15.webpack-compiler1
  • 103.15.webpack-compiler2
  • 103.16.rollup.1
  • 103.16.rollup.2
  • 103.16.rollup.3
  • 103.16.vite.basic
  • 103.16.vite.source
  • 103.16.vite.plugin
  • 103.16.vite.1
  • 103.16.vite.2
  • 103.17.polyfill
  • 104.1.binary
  • 104.2.binary
  • 105.skeleton
  • 106.1.react
  • 106.2.react_hooks
  • 106.3.react_router
  • 106.4.redux
  • 106.5.redux_middleware
  • 106.6.connected-react-router
  • 106.6.redux-first-history
  • 106.7.redux-saga
  • 106.8.dva
  • 106.9.umi
  • 106.10.ketang
  • 106.11.antdesign
  • 106.12.antpro
  • 106.13.router-6
  • 106.14.ssr
  • 106.15.nextjs
  • 106.16.1.cms
  • 106.16.2.cms
  • 106.16.3.cms
  • 106.16.4.cms
  • 106.16.mobx
  • 106.17.fomily
  • 107.fiber
  • 108.http
  • 109.1.webpack_usage
  • 109.2.webpack_source
  • 109.3.dll
  • 110.nest.js
  • 111.xstate
  • 112.Form
  • 113.redux-saga
  • 114.react+typescript
  • 115.immer
  • 116.pro5
  • 117.css-loader
  • 118.1.umi-core
  • 119.2.module-federation
  • 119.1.module-federation
  • 120.create-react-app
  • 121.react-scripts
  • 122.react-optimize
  • 123.jsx-runtime
  • 124.next.js
  • 125.1.linux
  • 125.2.linux-vi
  • 125.3.linux-user
  • 125.4.linux-auth
  • 125.5.linux-shell
  • 125.6.linux-install
  • 125.7.linux-system
  • 125.8.linux-service
  • 125.9.linux-network
  • 125.10.nginx
  • 125.11.docker
  • 125.12.ci
  • 125.13.k8s
  • 125.14.k8s
  • 125.15.k8s
  • 125.16.k8s
  • 126.11.react-1
  • 126.12.react-2
  • 126.12.react-3
  • 126.12.react-4
  • 126.12.react-5
  • 126.12.react-6
  • 126.12.react-7
  • 126.12.react-8
  • 127.frontend
  • 128.rollup
  • 129.px2rem-loader
  • 130.health
  • 131.hooks
  • 132.keepalive
  • 133.vue-cli
  • 134.react18
  • 134.2.react18
  • 134.3.react18
  • 135.function
  • 136.toolkit
  • 137.lerna
  • 138.create-vite
  • 139.cli
  • 140.antd
  • 141.react-dnd
  • 142.1.link
  • 143.1.gulp
  • 143.2.stream
  • 143.3.gulp
  • 144.1.closure
  • 144.2.v8
  • 144.3.gc
  • 145.react-router-v6
  • 146.browser
  • 147.lighthouse
  • 148.1.basic
  • 148.2.basic
  • 148.3.basic
  • 148.4.basic
  • 148.5.basic
  • 149.1.vite
  • 149.2.vite
  • 149.3.vite
  • 149.4.vite
  • 150.react-window
  • 151.react-query
  • 152.useRequest
  • 153.transition
  • 154.emotion
  • 155.1.formily
  • 155.2.formily
  • 155.3.formily
  • 155.3.1.mobx.usage
  • 155.3.2.mobx.source
  • 156.vue-loader
  • 103.11.mf
  • 157.1.react18
  • 158.umi4
  • 159.rxjs
  • 159.rxjs2
  • 160.bff
  • 161.zustand
  • 162.vscode
  • 163.emp
  • 164.cors
  • 1. sourcemap
    • 1.1 什么是sourceMap
    • 1.2 配置项
      • 1.2.1 source-map
      • 1.2.2 eval
      • 1.2.3 inline
      • 1.2.4 cheap(低开销)
      • 1.2.5 module
    • 1.3 演示
      • 1.3.1 安装
      • 1.3.2 webpack.config.js
      • 1.3.3 src\index.js
    • 1.4 最佳实践
      • 1.4.1 开发环境
      • 1.4.2 生产环境
  • 2. sourcemap
    • 2.1 生成sourcemap
    • 2.2 mappings属性
    • 2.3 位置对应的原理
    • 2.4 相对位置
    • 2.5 VLQ编码
    • 2.6 Base64 VLQ
    • 2.7 计算位移
  • 3.调试代码
    • 3.1 测试环境调试
    • 3.2 生产环境调试
  • 4.source-map-loader
    • 4.1 script.js
    • 4.2 script.min.js
    • 4.3 script.min.map.js
    • 4.4 src\index.js
    • 4.5 webpack.config.js
  • 3.参考

1. sourcemap #

1.1 什么是sourceMap #

  • sourcemap是为了解决开发代码与实际运行代码不一致时帮助我们debug到原始开发代码的技术
  • webpack通过配置可以自动给我们source maps文件,map文件是一种对应编译文件和源文件的方法
  • source-map

source-map

类型 含义
source-map 原始代码 最好的sourcemap质量有完整的结果,但是会很慢
eval-source-map 原始代码 同样道理,但是最高的质量和最低的性能
cheap-module-eval-source-map 原始代码(只有行内) 同样道理,但是更高的质量和更低的性能
cheap-eval-source-map 转换代码(行内) 每个模块被eval执行,并且sourcemap作为eval的一个dataurl
eval 生成代码 每个模块都被eval执行,并且存在@sourceURL,带eval的构建模式能cache SourceMap
cheap-source-map 转换代码(行内) 生成的sourcemap没有列映射,从loaders生成的sourcemap没有被使用
cheap-module-source-map 原始代码(只有行内) 与上面一样除了每行特点的从loader中进行映射
hidden-source-map 隐藏sourcemap
nosources-source-map 控制台能正确提示报错的位置而不暴露源码

1.2 配置项 #

  • 配置项其实只是五个关键字eval、source-map、cheap、module和inline的组合
关键字 含义
source-map 产生.map文件
eval 使用eval包裹模块代码
cheap 不包含列信息(关于列信息的解释下面会有详细介绍)也不包含loader的sourcemap
module 包含loader的sourcemap(比如jsx to js ,babel的sourcemap),否则无法定义源文件
inline 将.map作为DataURI嵌入,不单独生成.map文件

1.2.1 source-map #

src\index.js

let a=1;
let b=2;
let c=3;

dist\main.js

   ({
     "./src/index.js":
       (function (module, exports) {
         let a = 1;
         let b = 2;
         let c = 3;
       })
   });
//# sourceMappingURL=main.js.map

1.2.2 eval #

  • 用eval执行代码
  • whyeval
  ({
    "./src/index.js":
      (function (module, exports) {
        eval("let a=1;\r\nlet b=2;\r\nlet c=3;\n\n//# sourceURL=webpack:///./src/index.js?");
      })
  });
  • eval-source-map就会带上源码的sourceMap
  • 加了eval的配置生成的sourceMap会作为DataURI嵌入,不单独生成.map文件
  • 官方比较推荐开发场景下使用eval的构建模式,因为它能cache sourceMap,从而rebuild的速度会比较快
  ({
    "./src/index.js":
      (function (module, exports) {
        eval("let a=1;\r\nlet b=2;\r\nlet c=3;//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,In0=\n//# sourceURL=webpack-internal:///./src/index.js\n");
      })
  });

devtool: "eval-source-map" is really as good as devtool: "source-map", but can cache SourceMaps for modules. It’s much faster for rebuilds.

1.2.3 inline #

  • inline就是将map作为DataURI嵌入,不单独生成.map文件
  • inline-source-map
({
    "./src/index.js":
      (function (module, exports) {
        let a = 1;
        let b = 2;
        let c = 3;
      })
});
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIj

1.2.4 cheap(低开销) #

  • cheap(低开销)的sourcemap,因为它没有生成列映射(column mapping),只是映射行数
  • 开发时我们有行映射也够用了,开发时可以使用cheap
  • cheap-source-map

1.2.5 module #

  • Webpack会利用loader将所有非js模块转化为webpack可处理的js模块,而增加上面的cheap配置后也不会有loader模块之间对应的sourceMap
  • 什么是模块之间的sourceMap呢?比如jsx文件会经历loader处理成js文件再混淆压缩, 如果没有loader之间的sourceMap,那么在debug的时候定义到上图中的压缩前的js处,而不能追踪到jsx中
  • 所以为了映射到loader处理前的代码,我们一般也会加上module配置
  • cheap-module-source-map

1.3 演示 #

1.3.1 安装 #

cnpm i webpack webpack-cli webpack-dev-server babel-loader @babel/core @babel/preset-env style-loader css-loader less-loader less file-loader url-loader -D

1.3.2 webpack.config.js #

const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  mode:'development',
  devtool:'cheap-module-source-map',
  entry:'./src/index.js',
  module: {
      rules: [
        {
          test: /\.js$/,
          use: [{
            loader:'babel-loader',
            options:{
              presets:["@babel/preset-env"]
            }
          }]
        } 
      ]
  },
  plugins:[
    new HtmlWebpackPlugin({
      template:'./src/index.html'
    })
  ]
}

1.3.3 src\index.js #

import './sum';
sum(1,2);
//console.log(window.a.b);

1.4 最佳实践 #

1.4.1 开发环境 #

  • 我们在开发环境对sourceMap的要求是:快(eval),信息全(module),
  • 且由于此时代码未压缩,我们并不那么在意代码列信息(cheap),
  • 所以开发环境比较推荐配置:devtool: cheap-module-eval-source-map

1.4.2 生产环境 #

  • 一般情况下,我们并不希望任何人都可以在浏览器直接看到我们未编译的源码,
  • 所以我们不应该直接提供sourceMap给浏览器。但我们又需要sourceMap来定位我们的错误信息,
  • 这时我们可以设置hidden-source-map
  • 一方面webpack会生成sourcemap文件以提供给错误收集工具比如sentry,另一方面又不会为 bundle 添加引用注释,以避免浏览器使用。

2. sourcemap #

  • compiler官方下载
  • compiler前端镜像
  • base64vlq在线转换

2.1 生成sourcemap #

script.js

let a=1;
let b=2;
let c=3;
java -jar compiler.jar --js script.js --create_source_map ./script-min.js.map --source_map_format=V3 --js_output_file script-min.js

script-min.js

var a=1,b=2,c=3;

script-min.js.map

{
"version":3,
"file":"script-min.js",
"lineCount":1,
"mappings":"AAAA,IAAIA,EAAE,CAAN,CACIC,EAAE,CADN,CAEIC,EAAE;",
"sources":["script.js"],
"names":["a","b","c"]
}
字段 含义
version:Source Source map的版本,目前为3
file:转换后的文件名。 转换后的文件名
sourceRoot 转换前的文件所在的目录。如果与转换前的文件在同一目录,该项为空
sources 转换前的文件,该项是一个数组,表示可能存在多个文件合并
names 转换前的所有变量名和属性名
mappings 记录位置信息的字符串

2.2 mappings属性 #

  • 关键就是map文件的mappings属性。这是一个很长的字符串,它分成三层
对应 含义
第一层是行对应 以分号(;)表示,每个分号对应转换后源码的一行。所以,第一个分号前的内容,就对应源码的第一行,以此类推。
第二层是位置对应 以逗号(,)表示,每个逗号对应转换后源码的一个位置。所以,第一个逗号前的内容,就对应该行源码的第一个位置,以此类推。
第三层是位置转换 以VLQ编码表示,代表该位置对应的转换前的源码位置。
"mappings":"AAAA,IAAIA,EAAE,CAAN,CACIC,EAAE,CADN,CAEIC,EAAE;",

2.3 位置对应的原理 #

  • 每个位置使用五位,表示五个字段
位置 含义
第一位 表示这个位置在(转换后的代码的)的第几列
第二位 表示这个位置属于sources属性中的哪一个文件
第三位 表示这个位置属于转换前代码的第几行
第四位 表示这个位置属于转换前代码的第几列
第五位 表示这个位置属于names属性中的哪一个变量

首先,所有的值都是以0作为基数的。其次,第五位不是必需的,如果该位置没有对应names属性中的变量,可以省略第五位,再次,每一位都采用VLQ编码表示;由于VLQ编码是变长的,所以每一位可以由多个字符构成

如果某个位置是AAAAA,由于A在VLQ编码中表示0,因此这个位置的五个位实际上都是0。它的意思是,该位置在转换后代码的第0列,对应sources属性中第0个文件,属于转换前代码的第0行第0列,对应names属性中的第0个变量。

mappings1

2.4 相对位置 #

  • 对于输出后的位置来说,到后边会发现它的列号特别大,为了避免这个问题,采用相对位置进行描述
  • 第一次记录的输入位置和输出位置是绝对的,往后的输入位置和输出位置都是相对上一次的位置移动了多少

mappings2

2.5 VLQ编码 #

  • VLQ是Variable-length quantity 的缩写,是一种通用的、使用任意位数的二进制来表示一个任意大的数字的一种编码方式
  • 这种编码需要用最高位表示连续性,如果是1,代表这组字节后面的一组字节也属于同一个数;如果是0,表示该数值到这就结束了
  • 如何对数值137进行VLQ编码
    • 将137改写成二进制形式 10001001
    • 七位一组做分组,不足的补0 0000001 0001001
    • 最后一组开头补0,其余补1 10000001 00001001
    • 137的VLQ编码形式为10000001 00001001
let binary = 137..toString(2);
console.log(binary);//10001001
let padded = binary.padStart(Math.ceil(binary.length / 7) * 7, '0');
console.log(padded);//00000010001001
let groups = padded.match(/\d{7}/g);
groups = groups.map((group,index)=>(index==0?'1':'0')+group);
console.log(groups);// ['10000001','00001001']

2.6 Base64 VLQ #

  • 一个Base64字符只能表示6bit(2^6)的数据
  • Base64 VLQ需要能够表示负数,于是用最后一位来作为符号标志位
  • 由于只能用6位进行存储,而第一位表示是否连续的标志,最后一位表示正数/负数。中间只有4位,因此一个单元表示的范围为[-15,15],如果超过了就要用连续标识位了
  • 表示正负的方式
    • 如果这组数是某个数值的VLQ编码的第一组字节,那它的最后一位代表"符号",0为正,1为负;
    • 如果不是,这个位没有特殊含义,被算作数值的一部分
  • 在Base64 VLQ中,编码顺序是从低位到高位,而在VLQ中,编码顺序是从高位到低位

base64

let base64 = [
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
    'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
];
/**
 * 1. 将137改写成二进制形式  10001001
 * 2. 127是正数,末位补0 100010010
 * 3. 五位一组做分组,不足的补0 01000 10010
 * 4. 将组倒序排序 10010 01000
 * 5. 最后一组开头补0,其余补1 110010 001000
 * 6. 转64进制 y和I
 */
function encode(num) {
    //1. 将137改写成二进制形式,如果是负数的话是绝对值转二进制
    let binary = (Math.abs(num)).toString(2);
    //2.正数最后边补0,负数最右边补1,127是正数,末位补0 100010010
    binary = num >= 0 ? binary + '0' : binary + '1';
    //3.五位一组做分组,不足的补0   01000 10010 
    let zero = 5 - (binary.length % 5);
    if (zero > 0) {
        binary = binary.padStart(Math.ceil(binary.length / 5) * 5, '0');
    }
    let parts = [];
    for (let i = 0; i < binary.length; i += 5) {
        parts.push(binary.slice(i, i + 5));
    }// 01000 10010
    //4. 将组倒序排序 10010 01000
    parts.reverse();// ['00000','00001']
    //5. 最后一组开头补0,其余补1 110010 001000
    for (let i = 0; i < parts.length; i++) {
        if (i === parts.length - 1) {
            parts[i] = '0' + parts[i];
        } else {
            parts[i] = '1' + parts[i];
        }
    }
    //6.转64进制 y和I
    let chars = [];
    for (let i = 0; i < parts.length; i++) {
        chars.push(base64[parseInt(parts[i], 2)]);
    }
    return chars.join('')
}
let result = encode(137);
console.log(result);

2.7 计算位移 #

let base64 = [
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
    'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
];
function getValue(char) {
    let index = base64.findIndex(item => item == char);//先找这个字符的索引
    let str = (index).toString(2);//索引转成2进制
    str = str.padStart(6, '0');//在前面补0补到6位
    //最后一位是符号位,正数最后一位是0,负数最后一位为1
    let sign = str.slice(-1)=='0'?1:-1;
    //最后一组第一位为0,其它的第一位为1
    str = str.slice(1, -1);
    return parseInt(str, 2)*sign;
}
function decode(values) {
    let parts = values.split(',');//分开每一个位置
    let positions = [];
    for(let i=0;i<parts.length;i++){
        let part = parts[i];
        let chars = part.split('');//得到每一个字符
        let position = [];
        for (let i = 0; i < chars.length; i++) {
            position.push(getValue(chars[i]));//获取此编写对应的值
        }
        positions.push(position);
    }
    return positions;
}
let positions = decode('AAAA,IAAIA,EAAE,CAAN,CACIC,EAAE,CADN,CAEIC,EAAE');
//后列,哪个源文件,前行,前列,变量
console.log('positions',positions);
let offsets = positions.map(item=>[item[2],item[3],0,item[0],]);
console.log('offsets',offsets);
let origin = {x:0,y:0};
let target = {x:0,y:0};
let mapping=[];
for(let i=0;i<offsets.length;i++){
    let [originX,originY,targetX,targetY] = offsets[i];
    origin.x += originX;
    origin.y += originY;
    target.x += targetX;
    target.y += targetY;
    mapping.push(`[${origin.x},${origin.y}]=>[${target.x},${target.y}]`);
}
console.log('mapping',mapping);
positions [
  [ 0, 0, 0, 0 ],
  [ 4, 0, 0, 4, 0 ],
  [ 2, 0, 0, 2 ],
  [ 1, 0, 0, -6 ],
  [ 1, 0, 1, 4, 1 ],
  [ 2, 0, 0, 2 ],
  [ 1, 0, -1, -6 ],
  [ 1, 0, 2, 4, 1 ],
  [ 2, 0, 0, 2 ]
]
offsets [
  [ 0, 0, 0, 0 ],
  [ 0, 4, 0, 4 ],
  [ 0, 2, 0, 2 ],
  [ 0, -6, 0, 1 ],
  [ 1, 4, 0, 1 ],
  [ 0, 2, 0, 2 ],
  [ -1, -6, 0, 1 ],
  [ 2, 4, 0, 1 ],
  [ 0, 2, 0, 2 ]
]
mapping [
  '[0,0]=>[0,0]',
  '[0,4]=>[0,4]',
  '[0,6]=>[0,6]',
  '[0,0]=>[0,7]',
  '[1,4]=>[0,8]',
  '[1,6]=>[0,10]',
  '[0,0]=>[0,11]',
  '[2,4]=>[0,12]',
  '[2,6]=>[0,14]'
]

sourcemapmove

3.调试代码 #

3.1 测试环境调试 #

enablesourcemap

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');
const FileManagerPlugin = require('filemanager-webpack-plugin');
const webpack = require('webpack');
module.exports = {
  mode: 'production',
  devtool: false,
  entry: './src/index.js',
  resolveLoader:{
    modules:['node_modules','loaders']
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [{
          loader: 'babel-loader',
          options: {
            presets: ["@babel/preset-env"]
          }
        }]
      },
      {
        test: /\.scss$/,
        use: [
          { loader: 'style-loader' },
          {
            loader: 'css-loader',
             options: { 
              sourceMap: true,
              importLoaders:2
             }
          },
          //{ loader: "resolve-url-loader" },
          { loader: "resolve-scss-url-loader" },
          {
            loader: 'sass-loader',
            options: { sourceMap: true }
          }
        ]
      },
      {
        test: /\.(jpg|png|gif|bmp)$/,
        use: [
          { loader: 'url-loader' }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new webpack.SourceMapDevToolPlugin({
      append: '//# sourceMappingURL=http://127.0.0.1:8081/[url]',
      filename: '[file].map',
    }),
    new FileManagerPlugin({
      onEnd: {
        copy: [{
          source: './dist/*.map',
          destination: 'C:/aprepare/zhufengsourcemap/sourcemap',
        }],
        delete: ['./dist/*.map'],
        archive: [{ 
          source: './dist',
          destination: './dist/dist.zip',
        }]
      }
    })
  ]
}

3.2 生产环境调试 #

  • webpack打包仍然生成sourceMap,但是将map文件挑出放到本地服务器,将不含有map文件的部署到服务器,借助第三方软件(例如fiddler),将浏览器对map文件的请求拦截到本地服务器,就可以实现本地sourceMap调试
regex:(?inx)http:\/\/localhost:8080\/(?<name>.+)$
*redir:http://127.0.0.1:8081/${name}

fiddleproxy

4.source-map-loader #

  • source-map-loader从当前存在的源码(从sourceMappingURL)中提供出map源码
cnpm i source-map-loader -D

4.1 script.js #

let a=1;
let b=2;
let c=3;
java -jar compiler.jar --js script.js --create_source_map ./script-min.js.map --source_map_format=V3 --js_output_file script-min.js

4.2 script.min.js #

var a=1,b=2,c=3;
//# sourceMappingURL=script-min.js.map

4.3 script.min.map.js #

{
"version":3,
"file":"script-min.js",
"lineCount":1,
"mappings":"AAAA,IAAIA,EAAE,CAAN,CACIC,EAAE,CADN,CAEIC,EAAE;",
"sources":["script.js"],
"names":["a","b","c"]
}

4.4 src\index.js #

import './script-min.js';

4.5 webpack.config.js #

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');
const FileManagerPlugin = require('filemanager-webpack-plugin');
const webpack = require('webpack');
module.exports = {
  mode: 'development',
  devtool: 'inline-source-map',
  entry: './src/index.js',
  resolveLoader:{
    modules:['node_modules','loaders']
  },
  module: {
    rules: [
+      {
+        test: /\.js$/,
+        use: ["source-map-loader"],
+        enforce: "pre"
+      },
      {
        test: /\.js$/,
        use: [{
          loader: 'babel-loader',
          options: {
            presets: ["@babel/preset-env"]
          }
        }]
      },
      {
        test: /\.scss$/,
        use: [
          { loader: 'style-loader' },
          {
            loader: 'css-loader',
             options: { 
              sourceMap: true,
              importLoaders:2
             }
          },
          //{ loader: "resolve-url-loader" },
+          { loader: "resolve-scss-url-loader" },
          {
            loader: 'sass-loader',
            options: { sourceMap: true }
          }
        ]
      },
      {
        test: /\.(jpg|png|gif|bmp)$/,
        use: [
          { loader: 'url-loader' }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ]
}

3.参考 #

  • javascript_source_map算法
  • devtool

访问验证

请输入访问令牌

Token不正确,请重新输入