Heim  >  Artikel  >  Web-Frontend  >  Informationen zur Webpack-Front-End-Leistungsoptimierung (ausführliches Tutorial)

Informationen zur Webpack-Front-End-Leistungsoptimierung (ausführliches Tutorial)

亚连
亚连Original
2018-06-22 17:08:132225Durchsuche

Webpack ist in letzter Zeit das beliebteste Modullade- und Verpackungstool. Es kann verschiedene Ressourcen wie JS (einschließlich JSX), Kaffee, Stile (einschließlich weniger/sass), Bilder usw. verwenden. Dieser Artikel fasst hauptsächlich relevante Informationen zur Front-End-Leistungsoptimierung des Webpack-Lernprogramms zusammen. Freunde in Not können darauf zurückgreifen.

Vorwort

Es war einmal, als wir JS-Ressourcen wie oben gezeigt einführten ist jetzt sehr beliebt. In den letzten Jahren hat sich der Bereich der Web-Frontend-Entwicklung hin zu einer standardisierten Entwicklung entwickelt. Dies spiegelt sich in den folgenden zwei Punkten wider:

1. MVC-F&E-Architektur. Viele Vorteile (klare Logik, das Programm konzentriert sich auf die Trennung von Daten und Leistung, gute Lesbarkeit, was bei der Vermeidung und Behebung von Problemen hilfreich ist...)

2. Es gibt unzählige Konstruktionswerkzeuge. Viele Vorteile (Verbesserung der Teamzusammenarbeit, des technischen Betriebs und der Wartung sowie Vermeidung der manuellen Bearbeitung trivialer und sich wiederholender Arbeiten)

  • Modulare Entwicklung

  • Integration der Front-End-Implementierung der Leistungsoptimierungstheorie, Codekomprimierung, Zusammenführung, Cache-Steuerung, Extraktion von öffentlichem Code usw.

  • Andere umfassen beispielsweise die Verwendung von ES 6 oder CoffeeScript Schreiben Sie den Quellcode und erstellen Sie dann die Browserunterstützung ES5

Das Front-End macht also so viel Spaß, wenn es noch Projekte ohne Front-End- und Back-End-Trennung gibt, ist es das wirklich zu konservativ.

Mainstream-Build-Tools

Es gibt viele Build-Tools auf dem Markt, darunter Grunt, Gulp, Browserify usw. Diese und WebPack sind alles Paketierungstools. Aber WebPack weist auch die folgenden Eigenschaften auf:

Im Vergleich zu Grunt verfügt WebPack nicht nur über einen umfangreichen Satz an Plug-Ins, sondern auch über ein Ladesystem (Loader). Stellen Sie sicher, dass mehrere Standardlademethoden unterstützt werden, einschließlich ES6, CommonJS, AMD usw., über die Grunt und Gulp nicht verfügen.

Aus Sicht der Code-Verschleierung ist WebPack noch extremer

Der Code ist in Verarbeitungseinheiten (anstelle von Dateien) fragmentiert, wodurch die Dateifragmentierung flexibler wird.

P.S. Dies ist nur ein einfacher Vergleich, egal welcher besser oder schlechter ist. Tatsächlich können Tools die Anforderungen erfüllen. Der Schlüssel liegt in ihrer Verwendung. Hinter der Verwendung von Tools steht das Verständnis der Front-End-Leistungsoptimierung.

Einführung

Vor kurzem verwende ich Webpack, um die Leistung beim Laden des ersten Bildschirms zu optimieren Nachdem ich online gegangen bin, habe ich es hier einfach geteilt, zunächst ein Vergleichsbild der ersten Bildschirmdarstellung vor und nach der Optimierung.

Sie können sehen, dass die gesamte Downloadzeit von 3800 ms auf 1600 ms reduziert wurde.

Wenn wir Webpack verwenden, wählen wir normalerweise mehrere Eintragsdateien aus, um unseren eigenen Quellcode vom Bibliothekscode Dritter zu trennen. Dies ist der vorherige Code.

entry: {
 entry: './src/main.js',
 vendor: ['vue', 'vue-router', 'vuex', 'element-ui','echarts']
},
output: {
 path: config.build.assetsRoot,
 filename: utils.assetsPath('js/[name].[chunkhash].js'),
 chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
}

echarts ist sehr groß, daher ist die gepackte Vendor.js etwa 1,2 MB groß (nach der GZIP-Komprimierung) und echarts wird auf der Homepage nicht verwendet, daher habe ich später externe Elemente zum Hinzufügen verwendet der dritte Die Drittanbieter-Bibliothek wird über CDN eingeführt. Das Folgende ist der optimierte Code

Dies ist der Vorher-Nachher-Vergleich Optimierung.

Dann müssen wir zum HTML gehen, um die CDN in externen Dateien in Form eines Skript-Tags zu zitieren. Danach können Sie es in die entsprechende Datei importieren. Der Vorteil besteht darin, dass es nicht in alle Trunks gepackt wird, egal wie oft Sie es in vielen Vue-Dateien referenzieren Dies wird später ausführlich beschrieben. Dies ist der Effekt, der mit dem Webpack-Bundle-Analyzer-Plug-in gezeigt wird.

entry: {
 entry: './src/main.js',
 vendor: ['vue', 'vue-router', 'vuex', 'element-ui']
 },
 // 这里的output为base中的output,不是生产的output
 output: {
 path: config.build.assetsRoot,
 filename: '[name].js',
 libraryTarget: "umd",
 publicPath: process.env.NODE_ENV === 'production' ?
  config.build.assetsPublicPath : config.dev.assetsPublicPath
 },
 externals: {
 echarts: 'echarts',
 _: 'lodash'
 },

Wir werden sehen, dass Echarts und Lodash nicht in allen Js ohne Externals und nach der Verwendung von Externals angezeigt werden Wenn Sie es 10.000 Mal importieren, wird es kein einziges Mal verpackt, das ist erstaunlich~~).

Zwei weitere Punkte zu Externals -

1. Der Schlüssel in Externals wird im Import verwendet

var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
new BundleAnalyzerPlugin({
  // 可以是`server`,`static`或`disabled`。
  // 在`server`模式下,分析器将启动HTTP服务器来显示软件包报告。
  // 在“静态”模式下,会生成带有报告的单个HTML文件。
  // 在`disabled`模式下,你可以使用这个插件来将`generateStatsFile`设置为`true`来生成Webpack Stats JSON文件。
  analyzerMode: 'server',
  // 将在“服务器”模式下使用的主机启动HTTP服务器。
  analyzerHost: '127.0.0.1',
  // 将在“服务器”模式下使用的端口启动HTTP服务器。
  analyzerPort: 8888, 
  // 路径捆绑,将在`static`模式下生成的报告文件。
  // 相对于捆绑输出目录。
  reportFilename: 'report.html',
  // 模块大小默认显示在报告中。
  // 应该是`stat`,`parsed`或者`gzip`中的一个。
  // 有关更多信息,请参见“定义”一节。
  defaultSizes: 'parsed',
  // 在默认浏览器中自动打开报告
  openAnalyzer: true,
  // 如果为true,则Webpack Stats JSON文件将在bundle输出目录中生成
  generateStatsFile: false, 
  // 如果`generateStatsFile`为`true`,将会生成Webpack Stats JSON文件的名字。
  // 相对于捆绑输出目录。
  statsFilename: 'stats.json',
  // stats.toJson()方法的选项。
  // 例如,您可以使用`source:false`选项排除统计文件中模块的来源。
  // 在这里查看更多选项:https: //github.com/webpack/webpack/blob/webpack-1/lib/Stats.js#L21
  statsOptions: null,
  logLevel: 'info' //日志级别。可以是'信息','警告','错误'或'沉默'。
 })

2 Der Wert in Externals wird unter Fenster aufgerufen

Dann lassen Sie uns darüber sprechen, warum die Ausgabe Trunkhash anstelle von Trunk verwendet. Dies dient dem dauerhaften Caching. Lassen Sie uns kurz über den Unterschied zwischen den beiden sprechen –

trunk: Die Version nach jedem Build bedeutet, dass die Hashwerte aller Dateien nach dem Build gleich sind, wenn ich beispielsweise nur eine Datei ändere , alle Datei-Hashes werden am Ende gleich sein, sodass nicht alle Dateien zwischengespeichert werden und der Cache seine Bedeutung verliert.

Trunkhash: Erzeugt unterschiedliche Hash-Werte basierend auf jeder Datei. Wenn sich die Datei ändert, ändert sich der Hash und nur die entsprechende Datei wird geändert

然后我们肯定是要用到CommonsChunkPlugin,这个插件是用来抽取公共代码的,基本上99%的配置都是长这样子或者类似这样子用两个不同的commonschunkPlugin,但这从某方面来说并没有实现真正意义上的持久化缓存,这个一会我会通过webpack打包原理来详细解释其中的原因。。。。。。

new webpack.optimize.CommonsChunkPlugin({
 names: ['vendor','manifest']
})

在没用这个插件之前,我们的main.js和vendor.js会是这样子。。。

大家会看到我们这两个文件会有公共的部分,比如vue和element-ui,所以我们要抽取公共代码到vendor中,所以我们可以先这样配置

new webpack.optimize.CommonsChunkPlugin({
 name: 'vendor',
}),

但这样的话虽然可以提取公共代码,但我们会把runtime(webpack运行时的代码,一会在打包原理中会再次提到)也放到vendor中,这里面会维护一个trunk的文件列表,类似于这样,就是说我们改任意的代码,这个table里面的hash会变,所以vendor的hash也会变

,所以这没有实现真正的持久化缓存。这个hash table是按需缓存的打包出来的trunk包,一般都是通过require.ensure(就是vue-router中配置的page对应页面,按需加载)

所以我们就把name改为names,就是上面那个配置。因为使用这个插件,我们会把公共代码抽到第一个name中,把runtime放到最后一个name中,也就是我们所谓的“manifest”文件。

并且这个文件会比较小,通常都是2kb左右,所以build后会生成一个script标签,但这样的话就多了一个http请求,所以我们可以用另外一个插件(InlineManifestWebpackPlugin)将manifest.js内联进去。就会长这样子

再回到我们的CommonsChunkPlugin,现在我们随便改任何已存在的文件,vendor.js的hash都不会变,是的,貌似这就实现了持久化缓存。但是当我们新增一个模块,并且在入口文件中import一下,我们的vendor就会跟main一起变。很奇怪对吧,我们明明已经做了自己的源码跟第三方库分离,为什么vendor还会变(到现在应该没有任何一篇博客对此进行详细的说明)。下面我就详细的给大家解释下我的看法,如果大家发现有不对的地方还请指正。

再解释为什么之前,我们先简单了解下webpack的打包规则。

webpack一个entry对应一个bundle,这个bundle包括入口文件和其依赖的模块。其他按需加载的则打包成其他的bundle。还有一个比较重要的文件时manifest,它是最先加载的,负责打包其他的bundle并按需加载和执行。

manifest是一个自执行函数,熟悉angular的同学看第一行应该很了解,因为anguar1.3版本的源码中启动就是angular.bootstrap,对,这里也是一样。里面的modules变量就是对应模块函数,它是webpack处理的基本单位,就是说对应打包前的一个文件

这是js源文件,

这是打包后的文件,

所有的模块函数索引都是连续的(每个js文件生成一个trunkid!!!!!),像这种 /* 4 */ 对应的就是js文件,他通过打包就变成了一个个trunkid,仔细看会看到咱们打包前js文件里的export和require依赖都会统一转换成webpack模块。咱们说的webpackJsonp就是除manifest之外打包其他的文件的函数体。

简单说下main吧,这个图的trunkid是连续的,为了在一张图上显示,我截掉了trunk3-7.

这里面一共有三个参数,第一个是我当前文件的trunkid,它是唯一标识符,就是指main的trunkid,第二个就是打包的所有文件的模块函数,第三个是我要立即执行的trunkid模块函数。

ok,介绍这些就足够了。

然后我们再回过头来看看为什么我们所谓的commonschunkPlugin会变。刚才说过,有几个js就有几个trunkid。

Wenn wir also ein neues js hinzufügen und es in den Haupteintrag einführen, verpackt Webpack es erneut und meine Hauptdatei wird eine weitere Modulfunktion haben. Wie ich gerade sagte, erhöht sich die Trunkid nacheinander und wird nicht wiederholt. Daher lautet die ID des entsprechenden Anbieters +1. Es handelt sich um eine so subtile Änderung, die dazu führt, dass sich der Hash ändert.

Schauen Sie genau hin, diese beiden Anbieter haben beide 10272 Leitungen. Der einzige Unterschied ist, dass ich möchte Um diese Herstellerbibliothek selbst auszuführen, muss diese Datei nur über die Modulfunktionen Trunkid + 1 verfügen, damit sich der Hash ändert. Erinnern wir uns sorgfältig daran. Dies verdeutlicht auch die Bedeutung dieses Plug-Ins. OK, dieses Plug-In erledigt dies, aber aufgrund des Webpack-Verpackungsmechanismus generieren unterschiedliche Dateien unterschiedliche Turnkids , das ist also ein Wermutstropfen. Denken Sie daran, dass wir main.js im Allgemeinen nicht beiläufig ändern. Aus einer anderen Perspektive ist dies also die Implementierung von persistentem Caching. Aber was ist, wenn ich einfach den Hash des Anbieters unverändert lassen möchte?

Dieser Code kann implementiert werden. Wenn Sie vue-cli gut kennen, ist dies die offizielle Demo von vue-cli Besprechen Sie dies später. Erklären Sie es allen (ich kann wirklich nicht mehr schreiben ...).

Abschließend möchte ich Ihnen eine super nützliche Sache vorstellen, nämlich CDN. Unsere aktuelle Forderung besteht darin, Bilder an CDN und js online gehen zu lassen, aber die offizielle Erklärung besteht darin, CDN-Änderungen durch Ändern der Konfigurationsdatei vorzunehmen. Wenn Sie dies tun, werden alle meine Ausgaben an CDN gesendet, und alle Ajax-Anfragen werden gesendet domänenübergreifend.

Meine Lösung bestand zu Beginn darin, die Quelldateien einzeln zu ersetzen, was langsamer wäre. Noch wichtiger ist, dass das CDN-Image auch einen Hash-Wert hat Wenn Sie das Bild in Zukunft ersetzen, müssen Sie den entsprechenden Hash erneut ändern. Gibt es eine Möglichkeit, ihm zu erlauben, den Hash automatisch zu erhalten?

Ja, wir müssen den CDN separat im URL-Loader konfigurieren, damit js auf den Online-Pfad zugreifen kann und statische Ressourcen den CDN verwenden. Die beiden beeinflussen sich nicht gegenseitig.

Eine kurze Erinnerung: Der URL-Loader kann den Hintergrund in js nicht erkennen. Daher muss jede Adresse, auf die wir in js verweisen, zuerst dieses Bild importieren. Der URL-Loader analysiert und verpackt es .

Ich habe das Obige für Sie zusammengestellt und hoffe, dass es Ihnen in Zukunft hilfreich sein wird.

Verwandte Artikel:

So verwenden Sie die Videokomponente zum Abspielen von Videos im WeChat-Miniprogramm

So verwenden Sie die Audiokomponente im WeChat-Miniprogramm

So implementieren Sie die sekundäre Axios-Kapselung in Vue

Das obige ist der detaillierte Inhalt vonInformationen zur Webpack-Front-End-Leistungsoptimierung (ausführliches Tutorial). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn