【Webpack】之 配合後端渲染
為什麼學習Webpack?
- 對之前開發形式的厭煩,想打破
- 更好模組管理
- 安全,對檔案壓縮,使外者不易看出
- 減少重複工作
程式碼分割
- 分離業務程式碼 和 第三方依賴
- 分離業務程式碼 和 業務公共程式碼 和第三方依賴
- 分離首次載入 和 訪問後加載的程式碼
├─build # 編譯後生成的所有程式碼、資源(圖片、字型等,雖然只是簡單的從源目錄遷移過來)
├─node_modules # 利用npm管理的所有包及其依賴
├─index.html # 僅作為重定向使用
├─package.json # npm的配置檔案
├─webpack-config # 存放分拆後的webpack配置檔案
│ ├─base # 主要是存放一些變數
├─webpack.config.js # 生產環境的webpack配置檔案(無實質內容,僅為組織整理)
├─webpack.dev.config.js # 開發環境的webpack配置檔案(無實質內容,僅為組織整理)
├─src # 當前專案的原始碼
├─pages # 各個頁面獨有的部分,如入口檔案、只有該頁面使用到的css、模板檔案等
│ ├─alert # 業務模組
│ │ └─index # 具體頁面
│ ├─index # 業務模組
│ │ ├─index # 具體頁面
│ │ └─login # 具體頁面
│ │ └─templates # 如果一個頁面的HTML比較複雜,可以分成多塊再拼在一起
│ └─user # 業務模組
│ ├─edit-password # 具體頁面
│ └─modify-info # 具體頁面
└─public-resource # 各個頁面使用到的公共資源
├─components # 元件,可以是純HTML,也可以包含js/css/image等,看自己需要
│ ├─footer # 頁尾
│ ├─header # 頁頭
│ ├─side-menu # 側邊欄
│ └─top-nav # 頂部選單
├─iconfont # iconfont的字型檔案
├─imgs # 公用的圖片資源
└─layout # UI佈局,組織各個元件拼起來,因應需要可以有不同的佈局套路
├─layout # 具體的佈局套路
└─layout-without-nav # 具體的佈局套路
需要生產環境和開發環境
- 因為後端伺服器啟動,資源請求路徑就會改變。
- 開發環境熱模板更新
生產環境
- 提取公共程式碼
- 壓縮混淆
- 檔案壓縮 或是 Base64編碼
- 去除無用的程式碼
(1)html-load,html片段插入html
<%= require('html-loader!../../public-resource/components/header/header.html') %>
npm配置 :npm install html-loader --save-dev
不需要全域性配置html-loader(即不需要在module中配置)
詳見:http://www.imooc.com/article/18513
(2)提取css
- npm配置 :
npm install extract-text-webpack-plugin --save-dev
- 在plugin中配置
// 宣告
var ExtractTextPlugin = require('extract-text-webpack-plugin');
// 在plugin中配置
/* 抽取出chunk的css */
new ExtractTextPlugin('css/[name].css')
(3)如何在html中引入css檔案
在對應的js檔案中,require
(4)提取所有公用的部分(js)
如果引入的js檔案中有公共部分,則會被提取出來
new webpack.optimize.CommonsChunkPlugin({
name: 'commons/common',
filename: '[name].js',
minChunks: 4 // 出現4次,則提出
}),
(5)提取html
- npm配置 :
npm install html-webpack-plugin --save-dev
- 在plugin中配置
// 宣告
var HtmlWebpackPlugin = require('html-webpack-plugin');
// 因為每提取一個html,就要new HtmlWebpackPlugin
// 所以一個公共方法,進行提取
// 用於判斷是否為html檔案
function isHtmlFile(str) {
var objRegExp = /\.html/;
return objRegExp.test(str);
}
pageArr.forEach((page) => {
if (isHtmlFile(page)) {
page = page.substring(0, page.lastIndexOf('.'));
const htmlPlugin = new HtmlWebpackPlugin({
filename: `/pages/${page}.html`,
template: path.resolve(dirVars.pagesDir, `./${page}.html`),
chunks: ['commons/common', page], // 公共檔案需先匯入, 同時公共js也在這配置
xhtml: true
});
configPlugins.push(htmlPlugin);
}
});
(6)圖片匯入
- npm配置:
npm install file-loader url-loader img-loader --save-dev
- 在module中配置
{
test: /\.(png|jpg|jpeg|gif|webp)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name].[ext]',
limit: 8192,
publicPath: '',
outputPath: 'build/',
useRelativePath: true
}
},
{ // 用於壓縮
loader: 'img-loader',
options: {
pngquant: {
quality: 80
}
}
}
]
}
(7)iconfont
- npm配置 同 圖片匯入
- 在module中配置
{
// iconfont
test:/\.(eot|woff2|woff|ttf|svg)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name].[ext]',
limit: 8192,
publicPath: '',
outputPath: 'build/',
useRelativePath: true
}
}
]
}
(8)分生產環境和開發環境
devServer 與 ExtractTextPlugin 可能相沖突
開發模式用 style-loader
(9)Babel
npm install babel-loader babel-core babel-preset-env -save-dev
babel-core:babel的核心包;
babel-loader:babel的loader包;
babel-preset-env:解析es6的包;
// modules 中新增
{
test: /\.js$/,
include: dirVars.srcRootDir,
loader: 'babel-loader',
options: {
presets: [['env', { loose: true }]],
cacheDirectory: true,
plugins: ['transform-runtime', 'lodash']
}
}
函式和方法 沒有被 babel處理
比如:
- Generator
- Set
- Map
- Array.from
- Array.prototype.includes
npm install babel-polyfill babel-runtime --save-dev
全域性墊片
為開發應用準備
使用在 引入:import "babel-polyfill"
npm install babel-plugin-transform-runtime -save-dev
npm install babel-runtime -save-dev
區域性墊片
為開發框架準備
使用 新增檔案.babelrc
(10)Tree Shaking
使用場景(減少打包的程式碼,只打包使用到的程式碼,針對CSS和js)
- 常規優化
- 引入第三方庫的某一個功能
針對js進行過濾
// plugin 中新增
new webpack.optimize.UglifyJsPlugin()
針對CSS進行過濾 (Purify CSS)
purify css
npm install purifycss-webpack purify-css --save-dev
glob-all 處理多路徑
npm install glob-all --save-dev
var PurifyCss = require('purifycss-webpack');
var glob = require('glob-all');
針對lodash
npm install babel-plugin-lodash --save-dev
(11)Source Map 除錯
Why?
- 使開發程式碼與瀏覽器編譯後的程式碼一致
- 方便在瀏覽器中除錯,進行程式碼對映
新增 js source map
只需新增devtool: 'cheap-module-source-map'
當然cheap-module-source-map
根據需求進行更改
新增 css source map
只需在每個跟css有個的loader中的options下新增sourceMap: true
// 比如
{
loader: 'css-loader',
options: {
sourceMap: true
}
}
(12)EsLint檢查程式碼式格
安裝
npm install eslint eslint-loader eslint-plugin-html eslint-friendly-formatter --save-dev
npm install eslint-config-standard eslint-plugin-promise eslint-plugin-node eslint-plugin-import eslint-plugin-standard --save-dev
npm install babel-eslint --save-dev