Углубленная исходная карта

внешний интерфейс Webpack
Углубленная исходная карта

1. Что такое исходная карта

С точки зрения непрофессионала,Source MapЭто информационный файл, в котором хранится информация о местоположении после упаковки и преобразования кода, что по сути являетсяjsonФайл описания поддерживает отношения сопоставления кода до и после упаковки. оSource MapОбъяснение можно увидеть нижеIntroduction to JavaScript Source Maps.

Наш онлайн-код, как правило, упакован, и если онлайн-код сообщает об ошибке, его отладка будет очень трудоемкой, как в следующем примере:

Используйте инструменты для упаковкиWebpack, скомпилируйте этот фрагмент кода

console.log('source map!!!')
console.log(a); //这一行肯定会报错

Эффект после открытия браузера:

После нажатия войти в файл ошибки:

Невозможно найти конкретное место и причину этого, поэтому в настоящее времяSource MapЭффект наступает,WebpackВ коде сборки включитеSource Map:

Затем повторно выполните сборку и снова откройте браузер:

Можно обнаружить, что конкретное место ошибки может быть успешно обнаружено, чтоSource Mapэффект. Необходимо отметить, что,Source MapнетWebpackУникальные, другие инструменты упаковки также поддерживаютSource Map, инструмент упаковки просто преобразуетSource MapЭта технология внедряется через конфигурацию. Об инструменте упаковки будет введение ниже.

2. Роль исходной карты

Вышеприведенный случай как разSource MapПервый опыт, теперь поговорим о его роли и зачем он нам нуженSource Map ?

Учитель Руан ИфэнПодробная карта исходного кода JavaScriptОбратите внимание, что сценарии JavaScript становятся все более и более сложными. Большая часть исходного кода (особенно различные библиотеки функций и фреймворки) должна быть преобразована, прежде чем ее можно будет поместить в производственную среду.

Обычное преобразование исходного кода, в основном в следующих трех ситуациях:

  • сжать, уменьшить размер
  • Объедините несколько файлов, чтобы уменьшить количество HTTP-запросов.
  • Другие языки компилируются в JavaScript

Во всех трех случаях фактически работающий код отличается от кода разработки, отладки (debug) становится затруднительным, поэтому необходимоSource Map. В сочетании с приведенным выше примером, даже если код упакован, можно найти конкретное место ошибки, что заставляет насdebugКод сделан легко и просто, этоSource Mapпроблема, которую вы хотите решить.

3. Как создать исходную карту

Различные основные интерфейсные инструменты управления задачами и инструменты упаковки поддерживают генерациюSource Map.

3.1 UglifyJS

UglifyJSэто инструмент командной строки для сжатияJavaScriptкод

УстановитьUglifyJS:

npm install uglify - js - g

Одновременная генерация сжатого кодаSource Map:

uglifyjs app.js - o app.min.js--source - map app.min.js.map

Source MapСвязанные параметры:

--source - map Source Map的文件的路径和名称
    --source - map - root 源文件的路径
    --source - map - url //#sourceMappingURL的路径。 默认为--source-map指定的值。
    --source - map - include - sources 是否将源代码的内容添加到sourcesContent数组
    --source - map - inline 是否将Source Map写到压缩代码的最后一行
    -- in -source - map 输入Source Map, 当源文件已经经过变换时使用
3.2 Grunt

GruntдаJavaScriptинструмент сборки проекта

настроитьgrunt-contrib-uglifyплагин для генерацииSource Map:

grunt.initConfig({
    uglify: {
        options: {
            sourceMap: true
        }
    }
});

использоватьgrunt-useminПри упаковке исходного кодаgrunt-useminбудет вызываться последовательноgrunt-contrib-concatа такжеgrunt-contrib-uglifyУпакуйте и сожмите исходный код. Итак, все нужно настроить:

grunt.initConfig({
    concat: {
        options: {
            sourceMap: true
        }
    },
    uglify: {
        options: {
            sourceMap: true,
            sourceMapIn: function(uglifySource) {
                return uglifySource + '.map';
            },
        }
    }
});
3.3 Gulp

GulpдаJavaScriptинструмент сборки проекта

использоватьgulp-sourcemapsгенерироватьSource Map :

var gulp = require('gulp');
var plugin1 = require('gulp-plugin1');
var plugin2 = require('gulp-plugin2');
var sourcemaps = require('gulp-sourcemaps');

gulp.task('javascript', function() {
    gulp.src('src/**/*.js')
        .pipe(sourcemaps.init())
        .pipe(plugin1())
        .pipe(plugin2())
        .pipe(sourcemaps.write('../maps'))
        .pipe(gulp.dest('dist'));
});
3.4 SystemJS

SystemJSзагрузчик модулей

использоватьSystemJS Build ToolгенерироватьSource Map :

builder.bundle('myModule.js', 'outfile.js', {
    minify: true,
    sourceMaps: true
});
  • sourceMapContentsВозможность указать, следует ли писать исходный кодSource Mapдокумент
3.5 Webpack

WebpackЭто интерфейсный инструмент упаковки (этот инструмент упаковки будет использоваться во всех случаях в этой статье). в его конфигурационном файлеwebpack.config.jsустановить вdevtoolгенерироватьSource Mapдокумент:

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    devtool: "source-map"
};
  • devtoolСуществует более 20 различных значений, которые генерируют различные типыSource Map, который можно настроить по мере необходимости. Подробно он будет представлен ниже и не будет повторяться здесь.
3.6 Closure Compiler

использоватьClosure Compilerгенерировать

4. Как использовать исходную карту

генерироватьSource MapПосле этого обычно используется для отладки в браузере, при условии, что эту функцию нужно включить, чтобыChromeНапример:

Откройте инструменты разработчика и найдитеSettins:

Проверьте следующие два варианта:

Возвращаясь к приведенному выше случаю снова, файл исходного кода становитсяindex.js, щелкните, чтобы ввести и отобразить настоящий исходный код, что означает, что он был успешно открыт и использован.Source Map

Пять, принцип работы Source Map

Тем не менее в приведенном выше случае после выполнения упаковки сгенерированныйdistпапка, открытьdist/bundld.js:

Вы можете увидеть это примечание в конце:

//# sourceMappingURL=bundle.js.map

Именно из-за этого комментария файлSource Mapадрес, браузер может правильно найти местоположение исходного кода.sourceMappingURLнаправлениеSource MapдокументURL.

Помимо этого пути,MDNуказал, что черезresponse headerизSourceMap: <url>поле для указания.

> SourceMap: /path/to/file.js.map

distпапка, кромеbundle.jsа такжеbundle.js.map, этот файлSource Mapфайл тожеsourceMappingURLуказалURL

  • version:Source mapверсия, на данный моментv3.
  • sources: файл до преобразования. Этот элемент представляет собой массив, указывающий, что может быть несколько слияний файлов.
  • names: Все имена переменных и свойств перед преобразованием.
  • mappings: Строка, которая записывает информацию о местоположении, которая будет описана ниже.
  • file: преобразованное имя файла.
  • sourceRoot: Каталог, где файл перед преобразованием. Если файл перед преобразованием в тот же каталог, это пусто.
  • sourcesContent: Исходное содержимое файла до преобразования.
5.1 О версии исходной карты

в 2009GoogleВ статье, во введенииCloure Compilerчас,GoogleТакже воспользовался запуском средства отладки:FirefoxплагинClosure Inspector, чтобы облегчить отладку скомпилированного кода. ЭтоSource MapПервое поколение этого!

You can use the compiler with Closure Inspector , a Firebug extension that makes debugging the obfuscated code almost as easy as debugging the human-readable source.

В 2010 году во втором поколении именноClosure Compiler Source Map 2.0середина,Source MapобщепризнанныйJSONФормат и другие стандарты уже почти сформировались. Самая большая разница в том,mappingалгоритм тожеSource Mapключевой адрес. во втором поколенииmappingИспользовалbase 64кодирования, но алгоритм имеет доход и расход с текущим, поэтому сгенерированный.mapГораздо больше, чем сейчас. В 2011 году было выпущено третье поколение.Source Map Revision 3 ProposalОн вышел, и это то, что мы используем сейчасSource Mapверсия. Из названия документа текущийSource MapотстраненныйClousre CompilerЭволюция на независимую, а также получил поддержку браузера. Эта версия сравнивается со главным изменением второго поколенияmappingКонденсация алгоритма с использованиемVLQгенерация кодаbase64бывшийmapping, значительно уменьшается.mapРазмер файла.

Source MapСамое забавное в истории разработки то, что она разрабатывалась как вспомогательный инструмент. Ведь цель его помощи снижается, но он стал основным корпусом техники и прописан в браузере.

Исходный файл исходной карты, сгенерированный Source Map V1, примерно в 10 раз больше, чем преобразованный файл. Исходная карта V2 уменьшает его на 50%, а V3 уменьшает на 50% на основе V2. Итак, теперь размер файла исходной карты, соответствующего файлу размером 133 КБ, составляет около 300 КБ.

5.2 О свойстве сопоставления

Во избежание помех измените регистр на следующий без ошибок:

var a = 1;
console.log(a);

После упаковки и компиляцииbundle.jsдокумент:

/******/
(() => { // webpackBootstrap
    var __webpack_exports__ = {};
    /*!**********************!*\
      !*** ./src/index.js ***!
      \**********************/
    var a = 1;
    console.log(a);
    /******/
})();
//# sourceMappingURL=bundle.js.map

упаковано скомпилированоbundle.js.mapдокумент:

{
    "version": 3,
    "sources": [
        "webpack://learn-source-map/./src/index.js"
    ],
    "names": [],
    "mappings": "AAAA;AACA,c",
    "file": "bundle.js",
    "sourcesContent": [
        "var a = 1;\r\nconsole.log(a);"
    ],
    "sourceRoot": ""
}

можно увидетьmappingsСтоимость имущества составляет:AAAA; AACA, c, Чтобы прояснить эту вещь, вам нужно сначала объяснить ее структуру. Вот строка, она разбита на три слоя:

  • Первый слойкорреспонденция строки, представленный точкой с запятой (;), каждая точка с запятой соответствует строке преобразованного исходного кода. Таким образом, содержимое перед первой точкой с запятой соответствует первой строке исходного кода и так далее.
  • Второй слойместонахождение корреспонденция, представленный запятыми (, ), где каждая запятая соответствует позиции в преобразованном исходном коде. Следовательно, содержимое до первой запятой соответствует первой позиции исходного кода строки и так далее.
  • Третий слойпреобразование позицииVLQ-кодированиеПредставляет расположение исходного кода перед преобразованием, соответствующим этому местоположению.

Вернувшись к исходному коду, вы можете проанализировать:

  1. Поскольку в исходном коде две строки, перед и после точки с запятой стоит точка с запятой для обозначения первой и второй строк. которыйmappingsсерединаAAAAа такжеAACA,c.
  2. Вторая строка после точки с запятой - это кодconsole.log(a);Его можно разделить на две позиции, а именноconsoleа такжеlog(a), поэтому стоит запятая. которыйAACA,cсерединаAACAа такжеc.

Подводя итог, этоПреобразованный исходный код разделен на две строки, первая строка имеет одну позицию, а вторая строка имеет две позиции..

Что касается этогоAAAA,AAcAОткуда пришли письма, вы можете обратиться к г-ну Жуань Ифэну.Подробная карта исходного кода JavaScriptЕсть подробное введение. Собственное понимание автора таково:

AAAAа такжеAAcAтак же какcВсе они представляют позицию.Обычно каждая позиция состоит из букв 5. Значения 5 букв:

  • Первый бит указывает, в каком столбце (преобразованного кода) находится эта позиция.
  • Второй бит указывает, какому файлу в атрибуте sources принадлежит это местоположение.
  • Третий бит указывает, какой строке кода принадлежит эта позиция до преобразования.
  • Четвертая цифра указывает, к какому столбцу кода до конвертации относилась эта позиция.
  • Пятый бит указывает, какой переменной в атрибуте name принадлежит эта позиция.

Здесь после конвертации максимум 4 буквы, потому что нетnamesАтрибуты.

Доступно в любом местеVLQ-кодированиеПреобразуйте, чтобы сформировать отношение сопоставления. допустимыйэтот сайтКонвертируйте тест сами, будетAAAA; AACA, cПреобразованный результат:

Можно получить два набора данных:

[0, 0, 0, 0]
[0, 0, 1, 0], [14]

номера взяты из0начни, займи местоAAAAНапример, после преобразования получаем[0, 0, 0, 0], поэтому значения представителей таковы:

  1. Сжать первый столбец кода.
  2. Первый файл исходного кода, т.е.index.js.
  3. Первая строка исходного кода.
  4. исходный код первый столбец

Благодаря приведенному выше анализу мы можем узнать, что в исходном кодеvar a = 1;В упакованном файле, т.е.bundle.jsконкретное место.

6. Исходная карта в Webpack

описано вышеSource Mapфункция, принцип и т. Теперь поговорим об инструментах для упаковки.WebPackсредняя параSource MapПриложение, ведь мы в разработке, без него не обойтись.

Как было сказано выше, необходимо толькоwebpack.config.jsконфигурация в файлеdevtoolпросто используйтеSource Map,этоdevtoolКаковы конкретные значения, вы можете обратиться кwebpack devtool

, официальный список из 20 типов, конечно, мы не можем запомнить их все, мы можем вспомнить несколько ключевых:

Предлагаются следующие 7 вариантов:

  • source-map:внешний. Вы можете просмотреть точную информацию о коде ошибки и месте ошибки в исходном коде.
  • inline-source-map: в линию. генерировать только один встроенныйSource Map, вы можете просмотреть точную информацию о коде ошибки и местоположении ошибки в исходном коде.
  • hidden-source-map:внешний. Вы можете просмотреть точную информацию о коде ошибки, но вы не можете отследить ошибку исходного кода и можете только указать место ошибки кода после сборки.
  • eval-source-map: в линию. Каждый файл генерирует соответствующийSource Map, все вeval, вы можете просмотреть точную информацию о коде ошибки и местонахождение ошибки в исходном коде.
  • nosources-source-map:внешний. Вы можете просмотреть причину ошибки с кодом ошибки, но вы не можете просмотреть точную информацию о коде ошибки, и нет информации об исходном коде.
  • cheap-source-map:внешний. Вы можете просмотреть точную информацию о коде ошибки и местоположении ошибки исходного кода, только ошибка может быть точной для всей строки, игнорируя столбец.
  • cheap-module-source-map:внешний. Может ли код ошибки указывать точную информацию и местоположение ошибки исходного кода,moduleприсоединюсьloaderизSource Map.

Разница между встроенным и внешним:

  1. файлы, созданные извне (.map), встроенный нет.
  2. Встроенные сборки быстрее.

Следующие 7 типов демонстрируются на конкретных примерах:

Во-первых, измените регистр на состояние ошибки.Чтобы отразить ситуацию в столбце, измените исходный код следующим образом:

console.log('source map!!!')
var a = 1;
console.log(a, b); //这一行肯定会报错
6.1 source-map
devtool: 'source-map'

После компиляции вы можете просмотретьТочная информация о коде ошибки и местонахождение ошибки в исходном коде:

генерируется.mapдокумент:

6.2 inline-source-map
devtool: 'inline-source-map'

После компиляции вы можете просмотретьТочная информация о коде ошибки и местонахождение ошибки в исходном коде:

но не генерируется.map文件, но сbase64вставлен в формуsourceMappingURLсередина:

6.3 hidden-source-map
devtool: 'hidden-source-map'

После компиляции вы можете просмотретьКод ошибки точен, но местоположение исходного кода не видно:

генерируется.mapдокумент:

6.4 eval-source-map
devtool: 'eval-source-map'

После компиляции вы можете просмотретьТочная информация о коде ошибки и местонахождение ошибки в исходном коде:

но не генерируется.map文件, но вeval函数в том числеsourceMappingURL :

6.5 nosources-source-map
devtool: 'nosources-source-map'

После компиляции вы можете просмотретьНевозможно просмотреть точное местоположение кода ошибки и местоположение ошибки исходного кода, и можно только подсказать причину ошибки:

генерируется.mapдокумент:

6.6 cheap-source-map
devtool: 'cheap-source-map'

После компиляции вы можете просмотретьТочная информация кода ошибки и местонахождение ошибки исходного кода, но без учета определенных столбцов (因为是b导致报错):

генерируется.mapдокумент:

6.7 cheap-module-source-map

из-за необходимостиmodule, так что случай возрастаетloader:

module: {
    rules: [{
        test: /\.css$/,
        use: [
            // style-loader:创建style标签,将js中的样式资源插入进去,添加到head中生效
            'style-loader',
            // css-loader:将css文件变成commonjs模块加载到js中,里面内容是样式字符串
            'css-loader'
        ]
    }]
}

существуетsrcновый каталогindex.cssфайл, добавьте код стиля:

body {
    margin: 0;
    padding: 0;
    height: 100%;
    background-color: pink;
}

затем вsrc/index.jsПредставленindex.css:

//引入index.css
import './index.css';

console.log('source map!!!')
var a = 1;
console.log(a, b); //这一行肯定会报错

Исправлятьdevtool:

devtool: 'cheap-module-source-map'

После упаковки откройте браузер, стиль вступит в силу, объяснитеloaderВведен успешно. может просматриватьТочная информация кода ошибки и местонахождение ошибки исходного кода, но без учета определенных столбцов (因为是b导致报错):

генерируется.mapфайл тем временем будетloaderИнформация также упакована вместе:

6.8 Резюме

(1)среда разработки: необходимо учитывать высокую скорость и более удобную отладку.

  • высокоскоростной(eval > inline > cheap >... )
    1. eval-cheap-souce-map
    2. eval-source-map
  • Отладка более дружелюбна
    1. souce-map
    2. cheap-module-souce-map
    3. cheap-souce-map

В итоге получаются два лучших решения --> eval-source-map (высокая целостность, быстрая встроенная скорость) / eval-cheap-module-souce-map (подсказка об ошибке игнорирует столбцы, но содержит другую информацию, встроенная скорость быстрая)

(2)Производственная среда: вам нужно подумать, следует ли скрывать исходный код или нет, и должна ли отладка быть более удобной.

  • Встраивание сделает код больше, поэтому нет необходимости встраивать в производственной среде.
  • скрыть исходный код
    1. nosources-source-mapВсе скрыто (упакованный код и исходный код)
    2. hidden-source-mapСкройте только исходный код, он выдаст сообщение об ошибке кода после сборки.

В итоге получаются два лучших решения --> source-map (наиболее полная)/cheap-module-souce-map (ошибка предлагает целую строку игнорировать столбцы)

7. Резюме

Source MapЭто важно в нашем ежедневном процессе разработки, это может помочь нам отлаживать и находить ошибки. Хотя это включает в себя много точек знаний, таких как:VLQ,base64и т. д., но основное внимание мы уделяем тому, как это работает, и таким инструментам упаковки, какwebpackЭквивалентSource MapПриложения.

Source MapОчень мощный, не только используется в ежедневной разработке, но и может делать больше вещей, таких как性能异常监控平台. НапримерFunDebugЭтот веб-сайт черезSource MapВосстановите сжатый код в производственной среде, предоставьте полную информацию о стеке, точно определите местонахождение исходного кода ошибки и помогите пользователям быстро исправитьBug, таких случаев гораздо больше.

Короче говоря, учусьSource Mapочень нужно.

8. Ссылка