Webpack常用插件總結

剛完成一個基于React+Webpack的項目,漸漸地熟悉了Webpack的一些配置,開發過程中用到了不少Webpack插件,現在把覺得有用的Webpack插件總結一下當鞏固學習啦,主要涉及熱模塊替換[Hot Module Replacement]、ProvidePlugin、CommonsChunkPlugin、UglifyJsPlugin 、ExtractTextWebpackPlugin、DefinePlugin、DllPlugin等。

1、熱模塊替換Hot Module Replacement

熱模塊替換(HMR)是webpack提供的最有用的特性之一,熱模塊替換可以讓模塊在沒有頁面刷新的情況下實時更新代碼改動結果;

安裝webpack-dev-server

webpack-dev-server 是一個小型的Node.js Express服務器,它通過使用webpack-dev-middleware來為webpack打包的資源文件提供服務。可以認為webpack-dev-server就是一個擁有實時重載能力的靜態資源服務器(建議只在開發環境使用)
通過npm安裝:

npm install webpack-dev-server --save-dev```
運行

webpack-dev-server --open


##熱更新授權
一個簡單webpackHMR實例,這里感覺官方代碼比較簡單明了,直接復制過來啦
```javascript
const path = require('path');
const webpack = require('webpack');

module.exports = {
  entry: './index.js',

  plugins: [
    new webpack.HotModuleReplacementPlugin() // Enable HMR
  ],

  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/'
  },

  devServer: {
    hot: true, // Tell the dev-server we're using HMR
    contentBase: resolve(__dirname, 'dist'),
    publicPath: '/'
  }
};

上述代碼配置中需要注意兩個地方:
(1)plugins:添加webpack.HotModuleReplacementPlugin模塊熱更新插件
(2)devServer配置hot:true 開啟模塊熱更新配置,更多配置詳見devServer
同時還需注意的幾個devServer配置屬性

inline: true|false

inline屬性用于切換webpack-der-server編譯并刷新瀏覽器的兩種不同模式:
(1)第一種也是默認的inline模式,這種模式是將腳本插入打包資源文件中復制熱更新,并在瀏覽器控制臺中輸出過程信息,訪問格式訪問格式是http://<host>:<port>/<path>;
(2)iframe 模式:使用iframe加載頁面,訪問格式http://<host>:<port>/webpack-dev-server/<path>
可以通過配置

inline: false//啟用iframe
官方還是推薦使用inline模式

在你的代碼中插入熱替換代碼

index.js 在入口文件結尾處插入
if (module.hot) {
    module.hot.accept();
}

只有被 "accept"的代碼模塊才會被熱更新,所以你需要在父節點或者父節點的父節點... module.hot.accept 調用模塊。如以上代碼所示,在入口文件加入 module.hot.accept之后在入口文件引用的任何子模塊更新都會觸發熱更新。模塊更新完成,瀏覽器會輸出類型以下信息

熱更新輸出

也可以像官方提供的實例一樣accept特定的模塊,如下實例,當'./library'有任何更新是都會觸發熱模塊更新

import Lib from './library';

if (module.hot) {
  module.hot.accept('./library', function() {
    console.log('Accepting the updated library module!');
    Library.log();
  })
}

更多Hot Module Replacement資料參考

Hot Module Replacement
hot module replacement with webpack
webpack 熱加載你站住,我對你好奇很久了

2、ProvidePlugin

ProvidePlugin 可以在任何地方自動加載模塊而不需要import 或 require 方法:
例如:通過如下定義,在任何代碼中使用identifier變量,'module1'模塊都會被加載,identifier所代表的正式‘module1’模塊export的內容

new webpack.ProvidePlugin({
  identifier: 'module1',
  // ...
})

用途

(1)全局變量

如果你的項目里需要使用jQuery,如果每次使用的時候都需要通過import 或 require 去引入jQuery的話未免也太麻煩。這時候ProvidePlugin就可以幫上大忙了

//Webpack plugins定義
new webpack.ProvidePlugin({
  $: 'jquery',
  jQuery: 'jquery'
})
// 代碼模塊中調用
$('#item'); // <= 生效
jQuery('#item'); // <= just works
// $ is automatically set to the exports of module "jquery"

上述代碼可以看出通過ProvidePlugin定義的‘$’被調用時是直接生效的,webpack會自動把"jquery"給注入進模塊,而‘$’在模塊中則代表了‘jquery’ export的內容。這樣就不需要先let $=require('jquery')再調用啦。

(2)ProvidePlugin還可以根據不同環境使用不同配置

在實際的項目開發中我們通常會根據不同環境采用不同的webpack配置文件,如下代碼使用了三個不同文件代表了不同環境的配置,development.js、test.js、production.js分別代表了開發、測試、線上環境它們都輸出了一個包含name屬性的對象:

//development.js開發
module.exports = {
    name:'development'
};
//test.js測試
module.exports = {
    name:'test'
};

//production.js線上
module.exports = {
    name:'production'
};

//webpack.dev.config.js 開發環境
    new webpack.ProvidePlugin({
            ENV: 'development'
        })
//webpack.test.config.js 測試環境
new webpack.ProvidePlugin({
            ENV: "test"
        })
//webpack.pub.config.js 線上環境
    new webpack.ProvidePlugin({
            ENV: "production"
        })

假如在代碼模塊中這么調用

    if (ENV.name == 'development') {
      console.log('做一些開發環境的事情')
    } else if (ENV.name == 'test') {
      console.log('做一些測試環境的事情')
    } else if (ENV.name == 'production') {
      console.log('有些事情必須留到線上環境做')
    }

如上ProvidePlugin中定義的ENV在不同環境中就代表了不同模塊,這樣就可以區別的做一些開發、測試、生產環境不同的事情啦。

更多ProvidePlugin資料參考

ProvidePlugin
webpack 巧解環境配置問題

3、CommonsChunkPlugin

CommonsChunkPlugin是一個可以用來提取公共模塊的插件,配置:

{
  name: string, // or
  names: string[],
  // 這是 common chunk 的名稱。已經存在的 chunk 可以通過傳入一個已存在的 chunk 名稱而被選擇。
  // 如果一個字符串數組被傳入,這相當于插件針對每個 chunk 名被多次調用
  // 如果該選項被忽略,同時 `options.async` 或者 `options.children` 被設置,所有的 chunk 都會被使用,否則 `options.filename` 會用于作為 chunk 名。

  filename: string,
  // common chunk 的文件名模板。可以包含與 `output.filename` 相同的占位符。
  // 如果被忽略,原本的文件名不會被修改(通常是 `output.filename` 或者 `output.chunkFilename`)

  minChunks: number|Infinity|function(module, count) -> boolean,
  // 在傳入  公共chunk(commons chunk) 之前所需要包含的最少數量的 chunks 。
  // 數量必須大于等于2,或者少于等于 chunks的數量
  // 傳入 `Infinity` 會馬上生成 公共chunk,但里面沒有模塊。
  // 你可以傳入一個 `function` ,以添加定制的邏輯(默認是 chunk 的數量)

  chunks: string[],
  // 通過 chunk name 去選擇 chunks 的來源。chunk 必須是  公共chunk 的子模塊。
  // 如果被忽略,所有的,所有的 入口chunk (entry chunk) 都會被選擇。


  children: boolean,
  // 如果設置為 `true`,所有  公共chunk 的子模塊都會被選擇

  async: boolean|string,
  // 如果設置為 `true`,一個異步的  公共chunk 會作為 `options.name` 的子模塊,和 `options.chunks` 的兄弟模塊被創建。
  // 它會與 `options.chunks` 并行被加載。可以通過提供想要的字符串,而不是 `true` 來對輸出的文件進行更換名稱。

  minSize: number,
  // 在 公共chunk 被創建立之前,所有 公共模塊 (common module) 的最少大小。
}

webpack用插件CommonsChunkPlugin進行打包的時候,將符合引用次數(minChunks)的模塊打包到name參數的數組的第一個塊里(chunk),然后數組后面的塊依次打包(查找entry里的key,沒有找到相關的key就生成一個空的塊),最后一個塊包含webpack生成的在瀏覽器上使用各個塊的加載代碼,所以頁面上使用的時候最后一個塊必須最先加載。
打包公共文件

new webpack.optimize.CommonsChunkPlugin({
  name: "commons",
  // ( 公共chunk(commnons chunk) 的名稱)

  filename: "commons.js",
  // ( 公共chunk 的文件名)

  // minChunks: 3,
  // (模塊必須被3個 入口chunk 共享)

  // chunks: ["pageA", "pageB"],
  // (只使用這些 入口chunk)
})

配置例子:

文件目錄結構

image.png
//main.js
import A from './a'

//main1.js
import A from './a'
import B from './b'

//a.js
var A = 1;
exports.A = A;

//b.js
var B = 1;
exports.B = B;

//lib/jquery.js
var Jquery = 'fake jquery';
exports.$ = Jquery;

//lib/vue.js
var Vue = 'Fake Vue';
exports.Vue = Vue;

//package.json
{
  "name": "CommonsChunkPluginExample",
  "version": "1.0.0",
  "main": "main.js",
  "license": "MIT",
  "scripts": {
    "start": "webpack  --config webpack.dev.config.js "
  },
  "dependencies": {
    "webpack": "^2.6.1"
  }
}

實例代碼,以上main.js、main1.js為入口文件;a.js、b.js為代碼模塊文件;lib/jquery.js、lib/vue.js模擬代碼庫文件

打包main.js、main1.js的的公共模塊

var path = require('path')
var webpack = require('webpack')

module.exports = {
  entry: {
    main: './main.js',
    main1: './main1.js',
 },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js',
    chunkFilename: '[name].js',
  },
  resolve: {
    extensions: [' ', '*', '.js', '.jsx'],
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'commons'
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'load'
    })

  ],
}

按照預期
main.js、main1.js都引用了a.js,所以a.js被打包進commons.js中;b.js只被main1.js引用,將會被打包進main1.js中;打包生成的/dist/load.js包含了Webpack的加載代碼:

image.png
///dist/commons.js
webpackJsonp([2],[
/* 0 */
/***/ (function(module, exports) {

/**
 * Created by thea on 2017/6/9.
 */
var A = 1;
exports.A = A;

/***/ })
]);
//dist/main1.js

webpackJsonp([0],[
/* 0 */,
/* 1 */
/***/ (function(module, exports) {

var B = 1;
exports.B = B;

/***/ }),
/* 2 */,
/* 3 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__a__ = __webpack_require__(0);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__a___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__a__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__b__ = __webpack_require__(1);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__b___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1__b__);

/***/ })
],[3]);

提取第三方庫

在通常的項目開發中我們通常會引入一些第三方庫,在打包的時候我們通常也會希望將代碼拆分成公共代碼和應用代碼。將webpack.dev.config.js文件配置變化如下:

//webpack.dev.config.js
var path = require('path')
var webpack = require('webpack')

module.exports = {
  entry: {
    main: './main.js',
    main1: './main1.js',
    lib:['./lib/jquery.js','./lib/vue.js']//第三方庫
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js',
    chunkFilename: '[name].js',
  },
  resolve: {
    extensions: [' ', '*', '.js', '.jsx'],
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      names:['commons','lib']//'lib'提取入口entry key 'lib'代表的文件單獨打包
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'load'
    })
  ],
}

預期/lib/jquery.js、/lib/vue.js共同打包成為/dist/lib.js

image.png
///dist/lib.js
webpackJsonp([0],[
/* 0 */,
/* 1 */,
/* 2 */
/***/ (function(module, exports) {

var Jquery = 'fake jquery';
exports.$ = Jquery;

/***/ }),
/* 3 */
/***/ (function(module, exports) {

var Vue = 'Fake Vue';
exports.Vue = Vue;

/***/ }),
/* 4 */,
/* 5 */,
/* 6 */
/***/ (function(module, exports, __webpack_require__) {

__webpack_require__(2);
module.exports = __webpack_require__(3);


/***/ })
],[6]);

CommonsChunkPlugin更多資料參考

CommonsChunkPlugin
[webpack CommonsChunkPlugin詳細教程]
(https://segmentfault.com/a/1190000006808865)

4、ExtractTextWebpackPlugin 分離 CSS

Webpack打包默認會把css和js打包在一塊,然而我們通常習慣將css代碼中放在<head>標簽中,而將js引用放在頁面底部;將css代碼放在頁面頭部可以避免 FOUC 問題(表現為頁面內容已經加載出來,但是沒有樣式,過了一會兒樣式文件加載出來之后頁面回復正常);同時如果css和js分離也有利于這加強樣式的可緩存性;這是我們需要ExtractTextWebpackPlugin來分離js與css使得樣式文件單獨打包。

webpack處理css

在代碼中想JavaScript模塊一樣引入css文件

import styles from './style.css'

需要借助css-loader
style-loader

npm install --save-dev css-loader style-loader

在 webpack.config.js 中配置如下:

module.exports = {
    module: {
        rules: [{
            test: /\.css$/,
            use: [ 'style-loader', 'css-loader' ]
        }]
    }
}

這樣,CSS 會跟你的 JavaScript 打包在一起,并且在初始加載后,通過一個 <style> 標簽注入樣式,然后作用于頁面。

這里有一個缺點就是,你無法使用瀏覽器的能力,去異步且并行去加載 CSS。取而代之的是,你的頁面需要等待整個 JavaScript 文件加載完,才能進行樣式渲染。

使用 ExtractTextWebpackPlugin

安裝

npm install --save-dev extract-text-webpack-plugin

為了使用這個插件,它需要通過三步被配置到 webpack.config.js 文件中。

var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
    module: {
         rules: [{
             test: /\.css$/,
            use: ExtractTextPlugin.extract({
                     fallback: 'style-loader',
                    use: [
                        {
                            loader: 'css-loader',
                            options: {
                                sourceMap: true,
                                importLoaders: 1,
                                modules: true,
                                localIdentName: "[local]---[hash:base64:5]",
                                camelCase: true
                            }
                        }]
            })
         }]
     },
    plugins: [
        new ExtractTextPlugin( ({
            filename: '[name].css',//使用模塊名命名
            allChunks: true
        })
    ]
}

通過加入ExtractTextWebpackPlugin,每個模塊的css都會生成一個新文件,此時你可以作為一個單獨標簽添加到html文件中。

更多ExtractTextWebpackPlugin資料參考

webpack-contrib/extract-text-webpack-plugin
webpack ExtractTextWebpackPlugin

5、UglifyJsPlugin代碼壓縮輸出

代碼壓縮插件UglifyJsPlugin通過UglifyJS2來完成代碼壓縮,配置參考UglifyJS2
調用例子:

    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    })

6、設置全局變量插件[DefinePlugin

](https://webpack.js.org/plugins/define-plugin)

// webpack.config.js
const webpack = require('webpack');

module.exports = {
  /*...*/
  plugins:[
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production')
    })
  ]
};

通過DefinePlugin定義的變量可在全局代碼中使用,例如Webpack配置文件定義了process.env.NODE_ENV='production',如果代碼中存在如下調用:

if (process.env.NODE_ENV !== 'production') console.log('...') 

即等同于

if (false) console.log('...')

原理:DefinePlugin做的工作是在源代碼基礎上執行的全局查找替換工作,將DefinePlugin插件中定義的變量替換為插件中定義的變量值。

參考

DefinePlugin

DllPlugin& DllReferencePlugin

在前端項目構建中,為了提高打包效率,往往會將業務代碼合第三方庫打包。
之前有將將到過CommonsChunkPlugin可提供第三方庫單獨打包方法。但是由于每次運行Webpack,即使沒有代碼更新,也會重新打包,Webpack打包慢也是一直被詬病的問題,竟然減少打包內容才是王道;
其實Webpack還提供了一個提供了另外一個配置項Externals,提供了「從輸出的 bundle 中排除依賴」的方法:

index.html
...
<script src="https://code.jquery.com/jquery-3.1.0.js"
  integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
  crossorigin="anonymous"></script>
...
webpack.config.js
externals: {
  jquery: 'jQuery'
}

這樣就剝離了那些不需要改動的依賴模塊,換句話,下面展示的代碼還可以正常運行:

import $ from 'jquery';

$('.my-element').animate(...);

不過externals雖然解決了外部引用問題,但如果遇到像react模塊本身引入react入口文件,但是 Webpack 不知道這個入口文件等效于 react 模塊本身時,會出現重復打包現象,詳見徹底解決 Webpack 打包性能問題

Webpack提供了DllPlugin、DllReferencePlugin兩個插件,既能解決第三方庫代碼無變化仍然要打包增加打包時間問題,也能解決通過外鏈引用但可能第三方庫還是被打包進來的問題。

DllPlugin插件用來把需要獨立打包的第三方庫分離出來單獨打包最后會輸出兩個文件,一個是打包好的第三方庫bundle還有一個是用來給 DllReferencePlugin
映射依賴的manifest.json
使用方法:
(1)新建一個專門用來打包第三方庫的Webpack配置文件

//webpack.dll.config.js
const webpack = require('webpack');
module.exports = {
    entry: {
        react: ['./res/polyfill.js', 'react', 'react-dom', 'redux', 'react-redux', 'react-router']
    },
    output: {
          filename: '[name].bundle.js',
        path: path.join(__dirname, 'res'),
        library: '[name]_lib'
    },
    plugins: [
        new webpack.DllPlugin({
            path: '.res/[name]-manifest.json',//manifest.json輸出路徑,DllReferencePlugin需要用到

            name: '[name]_library',//打包庫文件名
           context:__dirname//可選,引用manifest.json的上下文,默認為Webpack配置文件上下文
        })
    ]
};

運行webpack.dll.config.js

webpack --config webpack.dll.config.js

生成打包好的庫bundle,和manifest.json文件 'bundle.manifest.json',大致內容如下:

{
 "name": "react_lib",
  "content": {
    "./node_modules/core-js/modules/_export.js": {
      "id": 0,
      "meta": {}
    },
    "./node_modules/core-js/modules/_global.js": {
      "id": 1,
      "meta": {}
    },
    "./node_modules/preact-compat/dist/preact-compat.es.js": {
      "id": 2,
      "meta": {
        "harmonyModule": true
      },
//其他引用
}

2、配置webpack.config.js中的插件DllReferencePlugin

    plugins: [
        new webpack.DllReferencePlugin({
            context: '.',//需要與webpack.dll.config.js中DllPlugin上下文一致
            manifest: require('./res/react-manifest.json')//DllPlugin輸出的manifest.json文件
        })]

通過兩步完美分離第三方庫~~~~

DllPlugin&DllReferencePlugin資料

DllPlugin
徹底解決 Webpack 打包性能問題
webpack dllPlugin 使用

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374

推薦閱讀更多精彩內容

  • GitChat技術雜談 前言 本文較長,為了節省你的閱讀時間,在文前列寫作思路如下: 什么是 webpack,它要...
    蕭玄辭閱讀 12,706評論 7 110
  • 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 webpack介紹和使用 一、webpack介紹 1、由來 ...
    it筱竹閱讀 11,208評論 0 21
  • 無意中看到zhangwnag大佬分享的webpack教程感覺受益匪淺,特此分享以備自己日后查看,也希望更多的人看到...
    小小字符閱讀 8,214評論 7 35
  • 最近在學習 Webpack,網上大多數入門教程都是基于 Webpack 1.x 版本的,我學習 Webpack 的...
    My_Oh_My閱讀 8,199評論 40 247
  • webpack 介紹 webpack 是什么 為什么引入新的打包工具 webpack 核心思想 webpack 安...
    yxsGert閱讀 6,488評論 2 71