This post is simultaneously posted on my Github personal blog

preface

A few days ago, when I was optimizing the project, I found that the sourcemap in development mode is cheap-module-sourcemap in the configuration of next. Config. js. Being – the module – the eval – source – the map.

Taking a look at the code that was added three years ago, I looked back at the SourcemAP configuration for WebPack and started a PR.

What is a Sourcemap

After our project was packaged, the source code in the development environment was compressed, whitespace removed, Babel compiled and other engineering transformations. There was a big difference between the final project code and the source code, which would cause problems that could not be debug. The code located in the online environment was the code after compression.

Sourcemap is a technology that helps us debug to the original developed code when the developed code is inconsistent with the actual running code. Sourcemap is a mapping between the source code and the target code where errors occur.

Sourcemap keywords

There are so many combinations of Sourcemap keywords that it is impossible to remember every use of Sourcemap one by one. We only need to know the meaning of a few keywords to predict the type of Sourcemap they will combine.

eval

Each module performs an eval() procedure, which does not generate a.map file, but appends // @sourceURL to each module to correlate the code before and after processing. You can speed up the rebuild process by wrapping module code in Eval. Therefore, sourcemap usually has the eval option, and the rebuild speed is faster.

webpackJsonp([1],[ function(module,exports,__webpack_require__){ eval( ... //# sourceURL=webpack:///./src/js/index.js?' )}, function(module,exports,__webpack_require__){ eval( ... //# SourceURL = webpack: / / /. / SRC/static/CSS/app. Less?. / ~ /. Npminstall/CSS - loader / 0.23.1 / CSS - loader!. / ~ /. Npminstall/postcss - load Er / 1.1.1 / postcss - loader! / ~ /. Npminstall/less - loader / 2.2.3 / less - loader ')}, function(module,exports,__webpack_require__){ eval( ... //# sourceURL=webpack:///./src/tmpl/appTemplate.tpl?" ) }, ...] )Copy the code

Why is the rebuild speed fast in eval mode?

Since the eval build can cache Sourcemap, the eval build can cache the Sourcemap for each module in a single line and add the Sourcemap as a DataURL. If no changes have been made, the sourcemAP will be used directly. Therefore, you only need to regenerate the sourcemAP for the changed module. However, the code generated in non-Eval build mode will affect the overall column and column format of the final bundle file regardless of any module changes, so it will have to regenerate the overall sourcemap each time, which will be very slow to rebuild.

source-map

A separate.map file is generated for each packaged module, and the.map file path is specified by appending sourceURI= to the end of the bundle, and you will see the webPack :// folder in the browser developer tools

webpackJsonp([1],[ function(e,t,i){...}, function(e,t,i){...}, function(e,t,i){...}, function(e,t,i){...}, ... ] )//# sourceMappingURL=index.js.mapCopy the code

A.map file is generated for each module in the packed directory. In this case, an index.js.map file is generated. This file is a typical sourcemap file in the following form:

{ "version":3, "sources":[ "webpack:///js/index.js","webpack:///./src/js/index.js", "Webpack: / / /. / ~ /. Npminstall/CSS - loader / 0.23.1 / CSS - loader/lib/CSS - base. Js",... , "names":["webpackJsonp","module","exports"...] , "mappings":"AAAAA,cAAc,IAER,SAASC..." , "file":"js/index.js", "sourcesContent":[...] , "sourceRoot":"" }Copy the code

cheap

Sourcemap, which contains neither column information nor loader, generates a.map file for each module, which differs from sourcemap in that it generates cheap and ignores the column information in the original code.

Because the generated Sourcemap does not have column information but only row information, compilation is less computationand therefore faster.

module

Include sourcemap between Loader modules (such as JSX syntax code compiled by Loader into native JS code) so that you can see the original code before loader processes it

inline

The normal generation of sourcemap is to create a. Map file in the dist directory, inline means that no separate. Map file is generated, and the sourcemap content is appended to the end of the bundle as a DataURI. Embed.map as DataURI. (Generally used this type such as caused by excessive volume, this type is less used)

webpackJsonp([1],[ function(e,t,i){...}, function(e,t,i){...}, function(e,t,i){...}, function(e,t,i){...}, ... ] ) //# sourceMappingURL=data:application/json; charset=utf-8; base64,eyJ2ZXJzaW9...Copy the code

DataURL was originally a reference to an image, such as a Base64 image, that appeared in the IMG tag of an HTML file

DataURL is used in the following scenario

  • Access to external resources is limited
  • Images are small in size and waste resources occupying an HTTP session

hidden

The bundle does not contain a reference to Sourcemap, so browser developer tools cannot see the original code

Sourcemap type

Several sourcemap types have been added to the mix

  • The eval – source – the map: After eval() is performed for each module, a.map file is generated for each module, and the generated sourcemap file is added as a DataURL (replacing the eval sourceURL with the DataURL for the full Sourcemap information).

  • Cheap-eval-source-map: Same as eval-source-map, except that “cheap” is added, which means row information is ignored. This property also does not generate sourcemaps between different Loader modules.

  • Cheap-module-eval-source-map: Same as cheap-eval-source-map, but includes sourcemap between different Loader modules

  • Cheap -source-map: does not contain column information and does not contain loader’s sourcemap

  • The inline – source – the map: Add the Sourcemap DataURL to each file, noting that the file is each file before packaging, not the last packaged, and that the DataURL is a Base64 formatted string containing the complete sourcemap information for a file

  • Hidden-source-map: Do not append the sourceURL to the end of the bundle to specify the location of its sourcemap file, but the sourcemap file will still be generated. In this way, browser developer tools cannot apply Sourcemap. The goal is to avoid sourcemap files being published to production and causing source code leakage.

There’s more than that, there’s more combinations, and that’s it

How do I select Sourcemap

  • First of all, the column information in the source code is not meaningful, because as long as there is a line information can completely establish the dependency between the packaged code, enough for us to locate.
  • Second, in both production and development environments, we need to locate debugging to the most primitive resources, such as the original JSX code, not the code compiled into JS. Therefore, we cannot ignore the Module attribute.
  • eval-source-mapUsing DataURL itself to contain the full Sourcemap information does not require the browser to send a full request to get the Sourcemap file, as with sourceURL, which makes it slightly more efficient

Use: cheap-module-eval-source-map in the development environment. (This configuration value preserves the original code information before loader processing and is a better choice because it is faster to package.)

Using Sourcemap in a production environment runs the risk of leaking the source code, but if you want to preserve errors on the locator line, you should prevent browser developer tools from seeing the source code and instead upload the Sourcemap files to the system using some error-collection system. Analyze the error stack of the original code through the system source map, such as hidden-source-map.

Of course, there are also nosource-source-map, source-map, according to your requirements of the scene to choose. In short, the end result is that no one can see the source code through developer tools.

conclusion

Our project is still Webpack4.x at present. If you have used Webpack5 in your project, the name of sourcemap is a little different. Please refer to the Webpack5 document for details.

reference

Sourcemap in Webpack and how to set the proper type of SourcemAP in production and development environments


Ps:

  • Personal tech blog Github repository