優(yōu)化前
webpack配置了兩個入口,一個是app.js
盹愚,一個是vendors
(包括 react 等第三方插件)皆怕。打包生成的JS文件對應(yīng)有兩個:app-[hash].js
和vendors.js
。
這種情況下西篓,樣式文件都被打包到了 app-[hash].js
里面端逼。而且這時候我們還沒有做按需加載,所以這個文件會比較大污淋,網(wǎng)頁初次加載的時候花的時間很長礁鲁。
優(yōu)化后
使用插件 extract-text-webpack-plugin
把樣式從JS文件中分離出來,生成一個單獨的CSS文件(竟然快1Mb了...)赁豆,再引入到 HTML 中仅醇。打開頁面的時候,app-[hash].js
魔种,vendors.js
和這個CSS文件會被異步加載析二,節(jié)省時間。
優(yōu)化過程
首先安裝插件:
npm install --save-dev extract-text-webpack-plugin
修改 webpack 配置文件节预,先添加plugin
:
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
... ...
plugins: [
... ...
new ExtractTextPlugin({ //樣式文件單獨打包
filename: "app.css", //指定生成的文件名稱
disable: false, //是否禁用此插件
allChunks: true
})
],
}
注意叶摄,如果是 Django 項目,樣式名稱需要跟打包生成的其中一個模塊名一樣安拟,這樣才能在 templates
中引入蛤吓。比如這里我們命名為app.css
。
然后修改CSS和LESS文件的loader
:
module: {
rules:[
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback:'style-loader',
use:['css-loader', 'postcss-loader'],
})
},
{
test: /\.less$/i,
use: ExtractTextPlugin.extract({
fallback:'style-loader',
use:['css-loader', 'less-loader'],
})
},
... ...
] // add all common loaders here
},
這是 Webpack 2 的配置了糠赦。Webpack 1 的 loader 格式跟上面的有一點區(qū)別会傲。
配置修改完成了,再打包就會出現(xiàn)一個 app.css
的文件拙泽。
接下來只需要在HTML頭部引入(如果不在意引入css的位置可以忽略以下的步驟)淌山。
我們后端使用的Django框架,所以需要在templates
中引入顾瞻。
修改前的 template
:
{% load render_bundle from webpack_loader %}
<!doctype html>
<html lang="en">
<head>
......
</head>
<body>
......
{% render_bundle 'vendors' %}
{% render_bundle 'app' %}
</body>
</html>
修改后:
{% load render_bundle from webpack_loader %}
<!doctype html>
<html lang="en">
<head>
{% render_bundle 'app' 'css' %}
</head>
<body>
<div id="app"></div>
{% render_bundle 'vendors' %}
{% render_bundle 'app' 'js' %}
</body>
</html>
具體修改:先指定在<body>
中只引入app bundle 的 js 文件:
{% render_bundle 'app' 'js' %}
然后在head
中引入app bundle對應(yīng)的 css 文件:
{% render_bundle 'app' 'css' %}
到這就ok了泼疑。
在django-webpack-loader
的使用說明中寫到了這個用法:
render_bundle
will render the proper<script>
and<link>
tags needed in your template.
render_bundle
also takes a second argument which can be a file extension to match. This is useful when you want to render different types for files in separately.
也就是說, render_bundle
會在template
中生成與bundle
對應(yīng)的 js 和 css 文件的 <script>
和 <link>
標(biāo)簽朋其。
而第二個可選參數(shù)用于指定引入的文件類型王浴,如果不指定的話,默認(rèn)兩個都會在指定位置生成梅猿。比如在分離CSS文件之后氓辣,如果不修改templates
,生成的HTML部分如下圖:
踩過的坑
- 注意CSS文件的名稱
在這種情況下钞啸,只能是app.css
或vendors.css
。也就是必須跟打包輸出的bundle中的其中一個同名喇潘。否則在打開頁面時會提示找到不到名稱為XXX的bundle之類的錯誤体斩。
- 不要在
template
中直接用<link>
標(biāo)簽引入導(dǎo)出的樣式文件
一開始我嘗試直接用<link>
標(biāo)簽引入導(dǎo)出的樣式文件,但是這樣沒有成功颖低,因為webpack開發(fā)模式和生產(chǎn)模式請求靜態(tài)文件的路徑不同絮吵。而django-webpack-loader
會幫我們根據(jù)配置生成不同的路徑。
比如{% render_bundle 'app' 'css' %}
在開發(fā)模式時會生成如下內(nèi)容:
<link type="text/css" href="http://localhost:3000/assets/bundles/app.css" rel="stylesheet"/>
而在生產(chǎn)模式時會生成:
<link type="text/css" href="/static/bundles/prod/app.css" rel="stylesheet"/>
這些路徑對應(yīng)開發(fā)模式的webpack配置:
config.output.publicPath = 'http://' + ip + ':3000' + '/assets/bundles/';
和 Django 配置文件中指定的靜態(tài)文件目錄STATICFILES_DIRS
忱屑,和bundle
目錄WEBPACK_LOADER
:
WEBPACK_LOADER = {
'DEFAULT': {
'BUNDLE_DIR_NAME': 'bundles/prod/', # change when production
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats-prod.json'), # change when production
}
}