webpack3.0學(xué)習(xí)筆記(三)

—— 擁抱html-webpack-plugin的甜蜜

目錄一覽

webpack3.0學(xué)習(xí)筆記(一)
webpack3.0學(xué)習(xí)筆記(二)
webpack3.0學(xué)習(xí)筆記(三)

項(xiàng)目源碼地址


前情概要

通過(guò)筆記(二)中一整天的試錯(cuò)發(fā)現(xiàn)了構(gòu)建多頁(yè)面時(shí)使用 html-loader 生成 html 文件的諸多弊病,重新回歸 html-webpack-plugin


html-webpack-plugin 構(gòu)建頁(yè)面

筆記(一)中對(duì) html-webpack-plugin 的理解略顯片面,用法得當(dāng)即可定制出一張滿足需求的頁(yè)面相满。

使用 html-webpack-plugin 插件對(duì)模板進(jìn)行填充完成 html 頁(yè)面的生成,其中的關(guān)鍵點(diǎn)是支持 ejs 的模板語(yǔ)法漱病。

  • html 模板內(nèi)容:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>this is webpack loader test</title>
    <link rel="stylesheet" href="<%= require('./style/index.css') %>">
    <link rel="stylesheet" href="<%= require('./style/one.css') %>">
</head>
<body>
    <img src="<%= require('./image/shana.jpg')%>" alt="shana" />
    <div class="yintama"></div>
</body>
</html>
  • webpack.config.js 配置:
const path = require('path')
const url = require('url')
const webpack = require('webpack')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    entry: {
        app: path.resolve(__dirname,'src/script/index.js'),
        one: path.resolve(__dirname,'src/script/one.js'),
        vendor: [
            'lodash'
        ]
    },
    output: {
        filename: 'js/[name].bundle.js',
        path: path.resolve(__dirname, 'dist'),
    },
    module:{
        rules: [
            {
                test: /\.js$/,
                use: 'babel-loader',
                include: path.resolve(__dirname,'src'),
                exclude: path.resolve(__dirname,'node_modules')
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name]-[hash:6].[ext]',
                            outputPath: 'css/'
                        }
                    },
                    "extract-loader",
                    {
                        loader: "css-loader",
                        options: {
                            minimize: true
                        }
                    }
                ]
            },
            {
                test: /\.(jpe?g|png|gif|svg)$/i,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            name: '[name]-[hash:6].[ext]',
                            outputPath: 'image/',
                            limit: 1,
                            publicPath: url.format({
                                hostname:'localhost',
                                protocol:'http:',
                                port:8080,
                                pathname:'/dist/'
                            })
                        }
                    },
                    'image-webpack-loader'
                ]
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin(['dist']),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname,'src/index.html'),
            filename: 'index.html'
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            minChunks: function(module){
                return module.context && module.context.indexOf("node_modules") !== -1;
            }
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: "manifest",
            minChunks: Infinity
        })
    ]
};

html 模板頁(yè)面中通過(guò) ejs 語(yǔ)法配合 webpack 靜態(tài)資源引入方法 require('xxx')铛碑,將其引入打包流程中,配合前兩篇筆記提及的幾個(gè) loader 對(duì)資源文件進(jìn)行優(yōu)化分離并獲取生成后地址病蛉,插入到新構(gòu)建的 html 頁(yè)面中。

注意:測(cè)試ES6的 import 'xxx' 的形式無(wú)法引入瑰煎,猜測(cè)是使用node進(jìn)行模塊引用铺然,暫時(shí)不支持該語(yǔ)法,使用 require('xxx') 即可酒甸。

如需將CSS文件也進(jìn)行合并操作魄健,在對(duì)應(yīng)的JS文件內(nèi)進(jìn)行引入,配合 css-loader style-loader 解析即可插勤。

項(xiàng)目的優(yōu)化手段

這里只用到了 uglifyjs诀艰, CommonsChunkPlugin 等方式,DLL打包類庫(kù)的問(wèn)題饮六,之后接構(gòu)建具體項(xiàng)目的時(shí)候再進(jìn)行嘗試。

  • 壓縮
  1. 圖片壓縮使用 image-webpack-loader

基本配置:

{
    test: /\.(jpe?g|png|gif|svg)$/i,
    use: [{
        loader: 'url-loader',
        options: {
            name: '[name]-[hash:6].[ext]',
            outputPath: 'image/',
            limit: 1,
            publicPath: url.format({
                hostname: 'localhost',
                protocol: 'http:',
                port: 8080,
                pathname: '/dist/'
            })
        }
    },
    {
        loader: 'image-webpack-loader',
        options: {
            gifsicle: {
                interlaced: false,
                optimizationLevel: 1
            },
            mozjpeg: {
                progressive: true,
                quality: 65
            }
        }
    }]
}

測(cè)試了下gif圖片的壓縮非常有限苛蒲,還是少用這種格式的圖片卤橄。

  1. CSS壓縮使用 css-loader
{
    test: /\.css$/,
    use: [{
            loader: 'file-loader',
            options: {
                name: '[name]-[hash:6].[ext]',
                outputPath: 'css/'
            }
        },
        "extract-loader", {
            loader: "css-loader",
            options: {
                minimize: true
            }
        }
    ]
}

CSS的壓縮直接使用loader進(jìn)行即可。

  1. JS壓縮使用 uglifyjs-webpack-plugin
    配置如下:
plugins: [
    new UglifyJSPlugin({
        sourceMap: true
    })
]

webpack 開啟了 devtool臂外,這里的 sourceMap 選項(xiàng)設(shè)為 true窟扑。

使用 uglifyjs-webpack-plugin 的時(shí)候正好說(shuō)說(shuō) webpacktree shaking 特性喇颁,雖然不是什么新東西,由于支持ES6的 import 導(dǎo)入語(yǔ)法才開始廣泛使用嚎货。

  1. tree shaking

two.js 代碼如下:

function name (){
    return 'Misery'
};

function age (){
    return 30
};

export {name,age}

index.js 內(nèi)容如下:

import {name} from './two.js';

function test(){
    var element = document.createElement('div');

    element.innerHTML = `hello ${name()}`;
    element.appendChild(btn);

    return element;
}

document.body.appendChild(test());

打包合并后如下:

未壓縮前

打包后 two.js 模塊中 nameage 方法都被打包了橘霎,但只有 name 方法被導(dǎo)出了模塊, age 由于沒有被調(diào)用而被忽略了殖属。

壓縮后

使用 uglifyjs-webpack-plugin 壓縮后 age 方法已經(jīng)被徹底剔除姐叁,這個(gè)方式對(duì)不是特別常用的公共模塊調(diào)用能起到精簡(jiǎn)代碼的作用,具體使用方法視項(xiàng)目而定洗显。

注意:如果項(xiàng)目中使用了 babel 可能會(huì)在 webpack 打包前就將代碼進(jìn)行轉(zhuǎn)義導(dǎo)致 tree shaking 不能生效外潜,因?yàn)檫@功能只支持ES6的 import方法,此時(shí)只需要使用 babel-preset-env 插件挠唆,并修改 .babelrc 文件处窥。

{
    "presets": [
      ["env", {
        "modules": false
      }]
    ]
  }

  • 提取公共模塊
    使用 webpack 自帶的 webpack.optimize.CommonsChunkPlugin 插件進(jìn)行公共模塊提取。
const path = require('path')
const webpack = require('webpack')

module.exports = {
    entry: {
        ...
        vendor: [
            'lodash'
        ]
    },
    output: {
        filename: 'js/[name].bundle.js',
        path: path.resolve(__dirname, 'dist'),
    },
    plugins: [
        ...
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            minChunks: function(module){
                return module.context && module.context.indexOf("node_modules") !== -1;
            }
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: "manifest",
            minChunks: Infinity
        })
    ]
};

entry 增加公共庫(kù)文件的chunk玄组,也可將 vue react 這些框架統(tǒng)一寫入此處滔驾,在插件處配置 webpack.optimize.CommonsChunkPlugin 的設(shè)置,minChunks 接收的類型是 NumberFunction俄讹。
當(dāng)為 Number 時(shí)表示 chunk 被引用的次數(shù)不低于設(shè)定值哆致,則會(huì)被合入 vendor 模塊;若為 Function颅悉,則根據(jù)函數(shù)返回值進(jìn)行判斷沽瞭,module.context && module.context.indexOf("node_modules") !== -1 該配置的含義為僅將 node_modules 目錄下的公共類庫(kù)、框架整合進(jìn) vendor 模塊內(nèi)剩瓶,而忽略項(xiàng)目中被多次調(diào)用的自建模塊驹溃。

名為 manifest 是個(gè)“貨物清單”的配置,是 webpack 中一個(gè)特有的配置延曙,目的是將 webpack 中的引導(dǎo)邏輯單獨(dú)提取到一個(gè)文件中豌鹤,將其他業(yè)務(wù)模塊中的引導(dǎo)模塊邏輯剔除,從而減少重復(fù)打包的問(wèn)題枝缔,減小單文件容量布疙。


總結(jié)

通過(guò)對(duì) html-webpack-plugin 的學(xué)習(xí),更方便的去構(gòu)建一張HTML頁(yè)面愿卸,同時(shí)處理靜態(tài)資源文件引入問(wèn)題灵临。對(duì) jscss趴荸、圖片等文件在生產(chǎn)環(huán)境進(jìn)行壓縮的方法儒溉,接觸了 webpacktree shaking 的使用方法。使用 CommonsChunkPlugin 分離公共模塊的方法发钝,并了解創(chuàng)建一個(gè) manifest 貨物清單文件的意義(分離 webpack 的引導(dǎo)邏輯)顿涣。
下章會(huì)結(jié)合一個(gè) vue 多頁(yè)面實(shí)例進(jìn)行構(gòu)建測(cè)試波闹,并引入 DLLPluginDLLReferencePlugin 插件,優(yōu)化打包速度涛碑。


尾巴

tree shaking 這塊卡了很久精堕,一直得不到理想效果,通過(guò)排查 才發(fā)現(xiàn)是 babel 提前轉(zhuǎn)義了ES6的 modules 引發(fā)的蒲障,需要引入 babel-preset-env 取消轉(zhuǎn)義ES6 modules 才得以解決歹篓!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市晌涕,隨后出現(xiàn)的幾起案子滋捶,更是在濱河造成了極大的恐慌,老刑警劉巖余黎,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件重窟,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡惧财,警方通過(guò)查閱死者的電腦和手機(jī)巡扇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)垮衷,“玉大人厅翔,你說(shuō)我怎么就攤上這事〔笸唬” “怎么了刀闷?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)仰迁。 經(jīng)常有香客問(wèn)我甸昏,道長(zhǎng),這世上最難降的妖魔是什么徐许? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任施蜜,我火速辦了婚禮,結(jié)果婚禮上雌隅,老公的妹妹穿的比我還像新娘翻默。我一直安慰自己,他們只是感情好恰起,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布修械。 她就那樣靜靜地躺著,像睡著了一般检盼。 火紅的嫁衣襯著肌膚如雪祠肥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音仇箱,去河邊找鬼。 笑死东羹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的属提。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼冤议,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了恕酸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蕊温,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后义矛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體发笔,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡了讨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了前计。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡残炮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缩滨,到底是詐尸還是另有隱情势就,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布脉漏,位于F島的核電站苞冯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏侧巨。R本人自食惡果不足惜舅锄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望司忱。 院中可真熱鬧皇忿,春花似錦畴蹭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至幔荒,卻和暖如春糊闽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背爹梁。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工右犹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人姚垃。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓念链,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親莉炉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子钓账,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • GitChat技術(shù)雜談 前言 本文較長(zhǎng),為了節(jié)省你的閱讀時(shí)間絮宁,在文前列寫作思路如下: 什么是 webpack梆暮,它要...
    蕭玄辭閱讀 12,691評(píng)論 7 110
  • 無(wú)意中看到zhangwnag大佬分享的webpack教程感覺受益匪淺,特此分享以備自己日后查看绍昂,也希望更多的人看到...
    小小字符閱讀 8,160評(píng)論 7 35
  • 前言 WebPack 是什么啦粹? WebPack 是什么,WebPack 可以看做是模塊打包機(jī):它做的事情是窘游,分析你...
    Promise__閱讀 1,128評(píng)論 3 12
  • 在現(xiàn)在的前端開發(fā)中唠椭,前后端分離、模塊化開發(fā)忍饰、版本控制贪嫂、文件合并與壓縮、mock數(shù)據(jù)等等一些原本后端的思想開始...
    Charlot閱讀 5,439評(píng)論 1 32
  • 三天二夜三座城,生活節(jié)奏很快赢织,做了人生多件大事情亮靴,下了幾個(gè)決擇于置。有驚喜,有意外,有收獲瞄桨,有失落讶踪。 ...
    小森_b811閱讀 435評(píng)論 0 1