在看這篇文章之前,需要你對構建多頁面應用有一定的基礎認識,如果沒有的話,可以先參考這篇文章webpack 構建多頁面應用。
多頁面應用是由一個個獨立的頁面組成。因此,細粒度的處理一個個單頁面是構建單頁面框架之後的一個重要實現。
因為所涵蓋的知識點較碎,所以就不按照頁面的位置結合組成元素來講,如:head, body, script等。這裏主要介紹head。因為script操作其實就是上一篇文章中已經介紹過的js操作,而body因為內容較多,需要另起一篇文章。
頁面的頭部
在上一篇文章中,我們講述瞭如何用html-webpack-plugin 生成一個html文件,其中使用了兩個配置項chunks,filename,前者指代頁面所要引入的js模塊,也就是我們常見的html頁面中的<script src="..."></script>形式,後者指代文件的名字。
那麼,在這一部分,要説的就是如何給不同的頁面配置生成不同的頁面<head>...</head>。我們都知道頁面頭部包括title、link/style、meta、script 這四部分組成,尤其前三者居多。
當然,在web前端開發中js很強大,我們可以用js直接控制,在不同頁面的入口js文件中寫相應的js代碼。
這種方法雖然可行,但維護起來比較麻煩,當你修改的時候,你需要查找一個個頁面。
相對來講,使用html-webpack-plugin提供的配置項,會使你的開發工作變得簡單起來。
html-webpack-plugin 插件的配置項
title 選項可以為頁面指定名字,meta 選項可以為頁面指定html文檔關聯信息,如:描述,作者等,favicon 可以為頁面添加一個小圖標。 修改 webpack.config.js,代碼如下:
...
nnew HtmlWebapckPlugin({
/* inital page */
filename: 'index.html',
chunks: ['index'],
/* page head */
title: 'index',
meta: {
'description': '這是首頁',
'keywords': 'webpack, multi-page, 首頁',
'author': 'https://github.com/lvzhenbang/
},
favicon: './assets/19884132.jpg'
})
...
這樣頭部常用的三個元素我們已經解決了兩個。那麼接下來就是解決link這個元素的。
注:有一個比較特殊的就是html頁面圖標<link rel="shortcut icon" href="19884132.jpg"> ,我們使用 html-webpack-plugin 插件的 favicon 選項已經解決。
link 和 style 部分的處理
這兩個元素常常被用來處理樣式。link 處理外部樣式,style 處理內聯樣式。
注:很多人會誤解,或曲解,這裏的樣式處理是這樣的:在定義的頁面入口文件,或者頁面入口文件引用的文件中,引入css文件,webapck會將這些樣式以內聯的形式或者link的形式注入到生成的html頁面中。
這樣我們的應用的目錄結構就變成如下這樣(本片文章使用如下的目錄結構,它也介紹了各個js文件對css文件的引用):
├── src
│ ├── common // 公用的模塊
│ │ ├── a.js // 引用了a.css
│ │ ├── b.js // 引用了b.css
│ │ ├── c.js // 引用了c.css
│ │ ├── d.js
├── assets // 靜態資源
│ ├── 19224132.jpg // 用來做頁面圖標
│ ├── css
│ │ ├── a.css
│ │ ├── b.css
│ │ ├── c.css
│ │ ├── main.css
│ │ ├── abutus.css
│ ├── uttils // 工具
│ │ ├── load.js // 工具代碼load.js
│ ├── index.js // 主模塊index.js (包含a.js, b.js, c.js, d.js),引用了main.css
│ ├── aboutUs.js // 主模塊aboutus.js (包含a.js, b.js),引用了main.css, aboutus.css
│ ├── contactUs.js // 主模塊contactus.js (包含a.js, c.js),引用了main.css
├── webpack.config.js // css js 和圖片資源
├── package.json
├── yarn.lock
處理為內聯樣式
如果是webpack3.x 推薦使用 css-loader,style-loader,extract-text-webpack-plugin;如果是webapck4.x推薦使用的 css-loader, mini-css-extract-plugin。
webpack3.x與webapck4.x都一樣,修改webpack.config.js如下:
...
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
]
},
...
因為mini-css-extract-plugin是專門為webpack4.x設計的,如果webapck3.x使用它會報錯。
處理為外部鏈接(link)
webpack3.x中webpack.config.js修改如下:
...
const ExtractTextPlugin = require('extract-text-webapck-plugin')
...
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
}
]
},
plugins: [
...
new ExtractTextPlugin({
filename: '[name].css'
})
]
webpack4.x中webpack.config.js修改如下:
...
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
...
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
}
]
},
plugins: [
...
MiniCssExtractPlugin()
],
從js文件中分離出css文件,webpack3.x藉助於extract-text-webpack-plugin,webpack4.x藉助於mini-css-extract-plugin,前者給不同的css代碼塊命名需要在extract-text-webapck-plugin的示例中配置,它使用的是內置的CommonsChunkPlugin插件的拆分原則,後者不需要配置分離css代碼塊的名字選項,後者藉助於SplitsChunkPlugin插件的拆分原則。
所以,它們的分離形式與js代碼塊一致。
webpack3.x為每個入口點生成了一個css文件,並提取了它們的公共代碼生成了一個新的css文件;webapck4.x為每個入口生成了一個css文件,並提取並生成了這些文件相互之間的公共文件(它和前者不同,後者更精細化,只要是某一個或者幾個文件有公共代碼就提取出來,然後生成新的文件)。
為什麼將css文件和js文件分的這麼細?是因為這樣可以顯著的減小首次加載頁面時請求文件的大小(lazyload),但是這樣做會增加HTTP的請求次數。
在多頁面應用的過程中,有的人喜歡將所有的css放在一個或兩個文件中,而不是像本文中那樣為每個頁面生成一個css文件,包括它們之間的共用文件。但在多頁面應用中,這樣精密的細分也有其好處。
相對來説,使用CommonsChunkPlugin拆分的css模塊更合理些,而使用SplitsChunkPlugin拆分的css模塊,則過於細化。
至於如何取捨,還需要根據實際情況來定。
當然,這裏面還有一些小的問題需要優化,後期我會視情況來寫相應的文章描述。
源代碼
webpack3.x multi-page
webpack4.x multi-page
構建多頁面應用系列文章
- webpack 構建多頁面應用——初探
- 構建多頁面應用——單個頁面的處理