Webpack 4.X 從入門到精通 - 第三方庫(六)

在開發的時候會時經常使用到第三方的庫或者框架,好比耳熟能詳的jquery。藉助它們能提升開發效率,可是如何在webpack中使用呢。這篇文章介紹兩個東西,如何使用第三方庫以及如何提取第三方庫。javascript

使用第三方庫

一、在入口文件當中直接導入

安裝jQuerycss

npm i jquery -S

目錄結構如圖:
圖6-1html

package.json內容以下:java

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.config.js",
  "scripts": {
    "build": "webpack --mode production",
    "dev": "webpack-dev-server --mode development"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^1.0.0",
    "file-loader": "^1.1.11",
    "html-webpack-plugin": "^3.2.0",
    "mini-css-extract-plugin": "^0.4.1",
    "url-loader": "^1.0.1",
    "webpack": "^4.16.3",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^3.1.5"
  },
  "dependencies": {
    "jquery": "^3.3.1"
  }
}

webpack.config.js內容以下:node

const path=require('path');
const HtmlWebpackPlugin=require('html-webpack-plugin');
const MiniCssExtractPlugin=require('mini-css-extract-plugin');

module.exports={
    entry:'./src/js/index.js',
    output:{
        path:path.resolve(__dirname,'dist'),
        filename:'js/index.js'
    },
    plugins:[
        new HtmlWebpackPlugin({
            title:'陳學輝',
            template:'./src/template.html',
            filename:'index.html'
        }),
        new MiniCssExtractPlugin({
            filename:'css/index.css'
        }),
    ],
    devServer:{
        host:'localhost',
        port:1573,
        open:true
    },
    module:{
        rules:[
            {
                test:/\.css$/,
                use:[
                    {
                        loader:MiniCssExtractPlugin.loader,
                        options:{
                            publicPath:'../'
                        }
                    },
                    'css-loader',
                ]
            },
            {
                test:/\.(jpg|png|gif)$/,
                use:[
                    {
                        loader:'url-loader',
                        options:{
                            limit:5 * 1024,
                            outputPath:'images'
                        }
                    }
                ]
            }
        ]
    }
}

templage.html內容以下:jquery

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title><%= htmlWebpackPlugin.options.title %></title>
    </head>
    <body>
        <div id="box">
            <p>這是自帶的div</p>
            <ul>
                <li><a href="#">red</a></li>
                <li><a href="#">green</a></li>
                <li><a href="#">blue</a></li>
            </ul>
        </div>
    </body>
</html>

index.css內容以下:webpack

#box{
    width: 800px;
    height: 500px;
    border: 5px solid #999;
    color: #00f;
    background: url(../images/img_01.jpg);
}

index.js內容以下:web

import '../css/index.css';
import $ from 'jquery';    //引入jquery

$('ul li:last-child').css('background','green');

npm run build後打開頁面會看到最後一個li標籤有了一個綠色的背景。若是你打開index.js文件後會發現jquery的代碼也被壓縮了進來。npm

這是引入第三方庫的一種方式,但這種方式會有一個問題,若是我僅僅只是引入而並無使用,在打包的時候依然會把第三方庫打包進來。若是你的代碼由第二位同窗接手,他爲了不出錯並不會直接把import刪掉,而會把使用這個庫的代碼刪掉,假如這個庫的代碼只剩下了import,那打包後的文件體積依然很大,即是一種浪費json

修改index.js以下:

import '../css/index.css';
import $ from 'jquery';    //引入jquery

//$('ul li:last-child').css('background','green');

npm run build後打開index.js,你會發現jquery的代碼依然被打包了

二、webpack.ProvidePlugin

  1. 自動加載模塊,而沒必要用import或require
  2. 若是加載的模塊沒有使用,則不會被打包
  3. 加載的模塊爲全局模塊,在全局均可以使用

修改webpack.config.js以下:

const path=require('path');
const HtmlWebpackPlugin=require('html-webpack-plugin');
const MiniCssExtractPlugin=require('mini-css-extract-plugin');

const webpack=require('webpack');    //引入webpack模塊,ProvidePlugin是webpack身上的一個插件

module.exports={
    entry:'./src/js/index.js',
    output:{
        path:path.resolve(__dirname,'dist'),
        filename:'js/index.js'
    },
    plugins:[
        new HtmlWebpackPlugin({
            title:'陳學輝',
            template:'./src/template.html',
            filename:'index.html'
        }),
        new MiniCssExtractPlugin({
            filename:'css/index.css'
        }),
        new webpack.ProvidePlugin({    //它是一個插件,因此須要按插件的用法new一個
            $:'jquery',    //接收名字:模塊名
        }),
    ],
    devServer:{
        host:'localhost',
        port:1573,
        open:true
    }
    
    ...

修改index.js內容以下:

import '../css/index.css';
$('ul li:last-child').css('background','green');

npm run build後打開index.html能夠看到同樣的效果
再次修改index.js內容以下:

import '../css/index.css';
//$('ul li:last-child').css('background','green');

npm run build後打開index.js能夠看到jquery的內容並無被打包進來。這種方式比上一種方式就智能的很,會根據你是否使用庫而決定是否打包。

提取第三方庫

對於提取第三方庫有兩種形式,第一種是在一個頁面裏引入了多個庫,最終全部的代碼都會打包到一個文件裏,若是引入的庫很是之多,那文件會很是大,不利於加載。第二種就是在多個頁面裏都引入了同一個庫,那會把這個庫打包屢次,形成資源浪費。因此就須要把第三方庫單獨提取出來,優化資源。

一、一個頁面引入多個庫

接着上面的代碼,再添加一個庫,這個庫的名字叫underscore,它裏面封裝了不少關於數組與對象的方法,我拿其中一個方法進行演示

npm i underscore -S

修改webpack.config.js裏的插件:

new webpack.ProvidePlugin({    //它是一個插件,因此須要按插件的用法new一個
    $:'jquery',    //接收名字:模塊名
    _:'underscore'  //引入underscore庫
}),

修改index.js以下

import '../css/index.css';

$('ul li:last-child').css('background','green');
console.log(_([1,2,3]).map(v=>v*3));    //使用underscore庫裏的map方法,此方法爲循環數組裏每一位數據,並把每位數據都乘以3,返回新數組

npm run build後打開index.html能看到控制檯有輸出了[3, 6, 9],說明underscore庫已經被打包到index.js裏。能夠分別註釋jqueryunderscore的使用代碼,npm run build後對比index.js的大小就能看出區別

提取第三方庫

optimization 優化

  • splitChunks 緩存組
  • 能被提取的條件
一、模塊被重複引用或者來自node_modules中的模塊
二、模塊壓縮前至少有30kb
三、按需(異步)請求的數量小於5個
四、初始化加載時,並行請求數量小於等於3

修改webpack.config.js裏的moudle.exports

module.exports={
    entry:{
        index:'./src/js/index.js',    //要把入口文件與第三方庫分開,因此要單獨的給名字
    },
    output:{
        path:path.resolve(__dirname,'dist'),
        filename:'js/[name].js'    //以key作爲輸出的名字
    },
    plugins:[
        //...
        new webpack.ProvidePlugin({
            $:'jquery',
            _:'underscore'
        }),
    ],
    devServer:{
        //...
    },
    module:{
        //...
    },
    optimization:{    //優化
        splitChunks:{
            cacheGroups:{//緩存組,一個對象。它的做用在於,能夠對不一樣的文件作不一樣的處理
                commonjs:{
                    name:'vender',        //輸出的名字(提出來的第三方庫)
                    test: /\.js/,        //經過條件找到要提取的文件
                    chunks:'initial'    //只對入口文件進行處理
                }
            }
        }
    }
}

npm run build以後有兩個文件,index.jsvender.js,其中vender.js裏放的就是jqueryunderscore的代碼。

說明:
optimizationwebpack的另外一個配置參數,它的意義在於優化。裏面的 splitChunks參數值用來放提取第三方庫的一些設置,好比:要提取同步仍是異步的模塊,這個模塊的引用次數達到多少能被提取等。可是放在這裏的參數會對全部要提取的模塊生效。若是不一樣的公共模塊要不一樣的對待的話就須要在 splitChunks.cacheGroups裏去定義
cacheGroups翻譯過來就是緩存組,能夠理解爲針對不一樣的要提取的公共部分進行單獨設置,好比上面例子中要針對js進行提取,因此就起了個名字叫 commonjs,那它是個對象,裏面放的就是單獨的配置參數

詳細說明請參考:https://webpack.js.org/plugin...

二、多個頁面同時引入一個庫

還有另外一種形式,像jquery,它在多個頁面裏都被引入了,由於打包只能針對單頁面進行打包,那就會在每一個頁面裏都打包一次jquery,形成資源浪費

新建a.jsb.js,內容以下:
a.js

import $ from 'jquery';

console.log('這是a.js');
console.log($('ul'));

b.js

import $ from 'jquery';

console.log('這是b.js');
console.log($('ul li'));

能夠看到兩個js文件都引入了jquery文件

修改webpack.config.js文件的module.exports

module.exports={
    entry:{
        a:'./src/js/a.js',
        b:'./src/js/b.js'
    },
    output:{
        path:path.resolve(__dirname,'dist'),
        filename:'js/[name].js'
    },
    plugins:[
        //須要兩個頁面,因此寫兩個new HtmlWebpackPlugin
        /*new HtmlWebpackPlugin({
            title:'陳學輝',
            template:'./src/template.html',
            filename:'index.html'
        }),*/
        new HtmlWebpackPlugin({
            title:'a頁面',
            template:'./src/template.html',
            filename:'a.html',
            chunks:['a'],    //引入對應的js,須要用到chunks
        }),
        new HtmlWebpackPlugin({
            title:'b頁面',
            template:'./src/template.html',
            filename:'b.html',
            chunks:['b'],
        }),
        new MiniCssExtractPlugin({
            filename:'css/index.css'
        }),
        
        //jquery已經單獨在a與b文件裏引入了,這裏就不須要了
        /*new webpack.ProvidePlugin({
            $:'jquery',    //接收名字:模塊名
            _:'underscore'
        }),*/
    ],
    devServer:{
        //...
    },
    module:{
        //...
    },
}

npm run build後結構以下圖,在dist下的js目錄裏分別看一下a.jsb.js的大小,這兩個文件裏都包含了jquery。再分別打開a.htmlb.html頁面正常運行,控制檯裏打印出了想要的內容。
圖6-2

這樣就是一種浪費了,咱們徹底能夠把jquery單獨提取出來,在兩個頁面裏分別引入。若是是多個頁面都引入同一個庫,那提取公共庫就會是剛需。

修改webpack.config.jsmodule.exports

module.exports={
    entry:{
        a:'./src/js/a.js',
        b:'./src/js/b.js'
    },
    output:{
        path:path.resolve(__dirname,'dist'),
        filename:'js/[name].js'    //以key作爲輸出的名字
    },
    plugins:[
        new HtmlWebpackPlugin({
            title:'a頁面',
            template:'./src/template.html',
            filename:'a.html',
            chunks:['a','vender'],    //vender爲提取出的公共部分,須要在頁面裏引入
        }),
        new HtmlWebpackPlugin({
            title:'b頁面',
            template:'./src/template.html',
            filename:'b.html',
            chunks:['b','vender'],
        }),
        new MiniCssExtractPlugin({
            filename:'css/index.css'
        }),
    ],
    devServer:{
        //...
    },
    module:{
        //...
    },
    optimization:{
        splitChunks:{
            cacheGroups:{
                common:{
                    name:'vender',
                    test: /\.js/,
                    chunks:'initial'
                }
            }
        }
    }
}

npm run build後結構目錄以下圖,再次看一下a.jsb.js的大小,相比前面是否小了不少?公共的jquery已經被提取出來了並放到了vender.js中。查看a.htmlb.html頁面源碼發現vender.js已經被引入了。
圖6-3

至此Webpack 4.X的內容已經所有寫完~

源碼下載:https://pan.baidu.com/s/1h9PS...

相關文章
相關標籤/搜索