1. 程式人生 > >【Webpack】之 配合後端渲染

【Webpack】之 配合後端渲染

為什麼學習Webpack?

  1. 對之前開發形式的厭煩,想打破
  2. 更好模組管理
  3. 安全,對檔案壓縮,使外者不易看出
  4. 減少重複工作

程式碼分割

  1. 分離業務程式碼 和 第三方依賴
  2. 分離業務程式碼 和 業務公共程式碼 和第三方依賴
  3. 分離首次載入 和 訪問後加載的程式碼
├─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 # 具體的佈局套路
需要生產環境和開發環境
  1. 因為後端伺服器啟動,資源請求路徑就會改變。
  2. 開發環境熱模板更新
生產環境
  1. 提取公共程式碼
  2. 壓縮混淆
  3. 檔案壓縮 或是 Base64編碼
  4. 去除無用的程式碼

(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

  1. npm配置 : npm install extract-text-webpack-plugin --save-dev
  2. 在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

  1. npm配置 : npm install html-webpack-plugin --save-dev
  2. 在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)圖片匯入

  1. npm配置: npm install file-loader url-loader img-loader --save-dev
  2. 在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

  1. npm配置 同 圖片匯入
  2. 在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處理
比如:
  1. Generator
  2. Set
  3. Map
  4. Array.from
  5. 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)

  1. 常規優化
  2. 引入第三方庫的某一個功能
針對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?
  1. 使開發程式碼與瀏覽器編譯後的程式碼一致
  2. 方便在瀏覽器中除錯,進行程式碼對映


    新增 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