Webpack從入門到上線


webpack是目前一個很熱門的前端打包工具,官網說得很清楚,webpack的出現就是要把requirejs干掉。同時它還提供了十分便利的本地開發的環境。網上並不容易找到一個講解得比較詳細完整的教程,本文結合實踐經驗,總結一套可用的開發和上線的配置和流程。

首先,Require JS有什么問題

RequireJs存在的問題

博主先是使用了RequireJs,后來又轉了webpack,綜合比較,requirejs確實存在一些缺點:

1.寫法比較笨拙

 需要把所有的依賴模塊寫在require函數里面,當模塊很多的時候,看起來逼格就不高了,感受如下: 

而webpack既兼容requirejs的寫法,也兼容commonjs的寫法,也就是說,使用webpack你既可以繼續像上面那樣寫,也可以像node那樣寫,感受如下:

var modules = {
        signHandler: require("module/sign-log"),
        chatHandler: require("module/chat-win"),
        mapHandler: require("lib/map"),
        util: require("lib/util")
    };

可以在需要的時候再去require,而不是搞個大括號把全部的模塊一下子寫到一起。(模塊的導出用module.exports = ....)

當然這兩種寫法不僅是感光上的區別,邏輯上也有區別。用中括號加載的模塊通常webpack是動態去加載,而沒有中括號是和主文件打包在一起的。

2. 沒有通用模塊的概念

例如有一個彈框模塊,用在登陸注冊,並且所有頁面都有登陸注冊,所以這是一個所有頁面的通用模塊。如果頁面的其它模塊都沒調到通用模塊里面的東西的話,用RequireJs沒什么問題。但是實際情況上不是這樣的,例如util模塊既會被登陸注冊的模塊調用,也會被很多其它模塊調用。這個時候合並壓縮就有問題了:合並后的通用模塊如common-app.js會帶上util的代碼、另外一個頁面的例如detail.js也會帶上util的代碼,以后一改util.js里面的東西,就會一並改動其它所有用到util的頁面js,就得重新打所有js的版本號。這樣無論對布署上線,還是對於用戶的緩存來說都是不利的。

 webpack可以把幾個文件的通用模塊抽出來單獨作為一個模塊common-chunk.js,引用的時候每個頁面先引一個common-chunk.js,再引一個該頁面自己的js文件如detail.js,原detail.js里面和其它js文件共用的模塊已經被提取到common-chunk.js里面。

3. 沒辦法直接動態合並壓縮一個需要異步加載的模塊

這個問題是這樣的,假設我的聊天模塊文件有500Kb這么大,並不希望一刷頁面就加載,而是用戶點了聊天再去加載。這個聊天模塊有一個入口文件和其它幾個模塊文件,我合並壓縮了入口文件,需要有一個輸出文件,而入口文件define的模塊名和壓縮優化后的輸出文件的路徑肯定是要不一樣的,但是壓縮之后他並不會自動去改變輸出文件的模塊名。這樣就導致你要手動去改一下壓縮文件的模塊名,不然會require不到。我之前找了一下,沒有找到解決方案,所以采取了一個壓縮兩次的比較笨拙的方法。

而webpack有一個文件束chunkFile的概念,它會自動去把需要異步加載的文件變成一個chunkFile,然后觸發加載的時候再去加載chunkFile。

4. 需要借助gulp等管理工具進行開發

webpack本身有一些插件和第三方的插件,可以在本地開一個webpack-dev-server,文件一保存的時候就會自動打包編譯js/css/less/sass等。

 

使用RequireJs雖然看起來缺點比較多,但是使用RequireJs也有webpack不具備的優點,那就是RequireJs開發的時候在瀏覽器里面,每個模塊都是單獨一個文件,跟本地文件保持一致,而webpack是把主文件和該文件都用到的模塊都打包成了一個文件,這樣在調試的時候就需要你去搜索找到要調試的位置,而使用requireJs直接根據第幾行就可以了。不過,考慮到使用webpack可以搭建一個很方便的本地開發環境,所以這個缺點也不是很明顯。

使用webpack

用一句概括就是:寫一個配置文件,然后執行下webpack,就可以把生成的文件輸出,可壓縮帶版本號,同時生成一個source-map文件,這個文件包含了每個模塊的js和css的實際(帶版本號)路徑,根據這個路徑就可以把html里面的js/css等換成真實的路徑。

webpack是一個打包的工具,它有一個重要的概念,就是把js/css/image/coffee都當成地位相等的資源,你可以在js里面require一個css,也可以require一個image。但是這種模式比較適用於React等框架,都是用js控制。

 webpack的其它幾個重要概念:

1. loader加載器

上面說到,各種各樣的資源都可以在webpack里面加載,而這些資源都需要相應的加載器,webpack才能識別,然后解析成正常的瀏覽器認識的資源。

換句話說,你可以給webpack加載各種各樣的資源:css/less/sass/png/babel等,然后在代碼里面進行管理。

例如要加一個sass的loader,需要先安裝:

npm install sass-loader node-sass

然后在配置文件添加一個loader:

{
    test: /\.sass$/,
    loaders: ["style", "css", "sass"]
},

這樣當你require(“hello.sass”)的時候,webpack就能處理這種.sass結尾的文件。這樣子有兩個好處,一個是webpack能夠自動編譯sass為css,另一個是require進來的style,webpack會把它解析成一個object,這個object的key就是類名,就可以在js使用樣式的類名,這種比較適合類似於react的開發模式。

2. 文件束chunk

上面提到的,會把動態加載的文件生成一個個的chunk,在配置文件的output里面加一行:

chunkFilename: "bundle-[id].js"

就會根據id區分不同動態加載的chunk文件,而這些chunk文件名對於我們來說是無關緊要,因為這個是webpack管理的,開發者無需關心叫什么又是怎么加載的。

3. webpack-dev-server

  這是webpack的一個插件,可以在本地開一個靜態服務,用來作為本地開發的重要工具。具體步驟就是html里面引用的資源用一個假的域名,如develop.com:

<script src="//develop.com/site/app-init.js"></script>

然后再把develop.com綁到本地回路:

     127.0.0.1 fedren.com

這樣請求就打到了本地的80端口。同時在本地開一個nginx監聽在80端口,nginx收到80端口的請求后,再把請求轉發到webpack的服務(默認是8080端口)。這樣就能夠實現本地開發,下文會具體介紹。

 

下面一步步介紹怎么配置和使用webpack

webpack的基本配置

首先,npm init創建一個node的配置文件package.json,然后安裝webpack:

npm install webpack
sudo npm install webpack -g //安裝一個全局的命令

再創建一個webpack.config.js文件,加入最基本的配置:

module.exports = {
    // The standard entry point and output config
    //每個頁面的js文件
    entry: {
        home: "js/home",
        detail: "js/detail"
    },
    output: {
        path: "assets",                   //打包輸出目錄
        publicPath: "/static/build/",     //webpack-dev-server訪問的路徑
        filename: "[name].js",            //輸出文件名
        chunkFilename: "bundle-[id].js"   //輸出chunk文件名
    }
};

工程的js都放到js目錄下,一個叫home.js,另一個叫detail.js,輸出到assets目錄,publicPath是為webpack-dev-server所使用

然后在當前目錄執行webpack,發現webpack報錯了:

ERROR in Entry module not found: Error: Cannot resolve module 'js/home' in /Users/yincheng/code/blog-webpack

找不到js/home的模塊,只要在配置里面加一句resolve:

    resolve: {
        modulesDirectories: ['.']
    }

告訴webpack所有模塊的啟始目錄由當前目錄開始,再執行下webpack就可以正常輸出了:

到目前為此,當前工程的目錄結構就是這樣的了:

接下來,創建html:home.html,里面引入js文件,"static/build"即為上面定義的publicPath:

<body>
    <p>home.html</p>
    <script src="//develop.com/static/build/home.js"></script>
</body>

注意我們用了一個develop.com的域名,把這個域名綁到本地回路:

127.0.0.1 develop.com

然后配置nginx,打開nginx.conf,加多一個server:

    server {
        listen       80;
        server_name  payment-admin.com;
        charset utf-8;
        #工程路徑
        root    /Users/yincheng/code/demo;
        autoindex       on;
        autoindex_exact_size    on;

        location ~* /.+\.[a-z]+$ {
            proxy_set_header x-request-filename $request_filename;
            # webpack的服務
            proxy_pass http://127.0.0.1:8080;
        }
     }

啟動nginx或者重啟下nginx

然后再裝一個webpack-dev-server:

npm install webpack-dev-server --save-dev
sudo npm install webpack-dev-server -g

然后啟動webpack-dev-server,執行:

webpack-dev-sever --port=8080 //不加port參數,默認就為8080端口

然后就可以訪問:http://develop.com/html/home.html

這個時候,只要一改變home.js的內容,webpack-dev-server就會自動打包新的文件 ,一刷新頁面,就是最新的修改了。這樣就實現了最基本的本地開發,不管你用的jsp/php,都不需要把js/css往服務器上傳。 注意webpack-dev-server是在內存生成的文件,你在本地是找不到static/build目錄的,只有執行了webpack打包才會輸出文件到assets目錄。一個為上面配置里的publicPath,另一個為path。

 

引入樣式文件——首先創建css/home.css:

body{
    color: #f00;
}

然后在js里面引入這個css文件:

require("css/home.css");

一保存之后,會發現webpack-dev-server報錯了:

ERROR in ./css/home.css
Module parse failed: /Users/yincheng/code/blog-webpack/css/home.css Unexpected token (1:4)
You may need an appropriate loader to handle this file type.

根據提示,我們需要加裝一個css loader,讓webpack能夠處理css文件,更改webpack.config.js,加入一個loader:

module.exports = {
    entry: ...,
    output: ...,
    resolve: ...,
    module: {
        loaders: [
            {
                test: /\.css$/,
                loader: "style-loader!css-loader"
            },
        ]
    }
};

當然要先安裝一下:npm install style-loader css-loader --save-dev,然后再重啟下webpack-dev-server,就可以加載樣式了,我們發現webpack是把樣式動態插到了head標簽的style里面,但是一般並不希望直接寫到head里面,而是獨立的一個css文件,這個時候借助一個分離css的插件就可以了:

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

同時把配置文件的loader改一下:

var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
    module: {
        loaders: [
            // Extract css files
            {
                test: /\.css$/,
                loader: ExtractTextPlugin.extract("style-loader", "css-loader")
            },
        ]
    },

    plugins: [
        new ExtractTextPlugin("[name].css")
    ]
};

就會生成和js相同路徑和名字的css文件,在home.html里面引入css文件:

<link rel="stylesheet" href="//develop.com/static/build/home.css"></link> 

你也可以加載各種各樣的loader,如加載一個sass/less loader,require一個sass/less文件后就可以寫sass/less了,webpack會把它編譯成和上面一樣普通的css文件,讀者可以自己試試,還可以再裝一個png/jpg的loader,指定一個小於多少個k的圖片的參數,webpack就會把小於指定尺寸的圖片轉成base64的格式。各種loader的安裝查一查就有了。

 到這里一個最基本的本地開發環境就已經搭起來了。接下來討論自動刷新

自動刷新

上面一保存js/css的時候,webpack server就會自動打包,刷新頁面的時候就是最新的修改。這個刷新只要使用webpack的hot模式就可以自動實現,即一保存就自動打包刷新。將上面運行webpack-dev-server的命令再加多兩個參數,按照官方文檔的方式:

webpack-dev-server --port=8383 --hot --inline

如果沒有意外,在你的電腦上將會報錯:

ERROR in multi home
Module not found: Error: Cannot resolve module 'webpack/hot/dev-server' in /Users/yincheng/code/blog-webpack
 @ multi home

這個問題困惑了筆者好久,因為在node_modules里面是有這個"webpack/hot/dev-server"的,其實只要認真看下上面的提示,就會發現它並不是說在node_modules里面,而是在當前工程目錄里,所以把node_modules里的webpack文件夾拷一份到外面就可以正常運行了。(如果你又配了個context的參數的話,那就根據提示拷到context指定的目錄)

使用hot模式,只要一保存js/css就可以自動刷新了,這個功能確實很方便。如果不寫參數,也可以把它寫在配置文件里面:

var hotModuleReplacementPlugin = require("webpack/lib/HotModuleReplacementPlugin");
module.exports = {
    plugins: [
        new ExtractTextPlugin("[name].css"),
        new hotModuleReplacementPlugin()
    ],
    devServer: {
        historyApiFallback: true,
        hot: true,
        inline: true,
        progress: true }
};

然后運行server就不用帶上后面那兩個參數了。

Common chunk

如上文提到,webpack可以將幾個js的公共模塊提取成一個chunk,需要借助一個commonChunkPlugin,在上面的plugins再添加一個:

var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
plugins: [
        new CommonsChunkPlugin({
            //minChunks: 3,
            name: "common-app.chunk",
            chunks: ["home", "detail", "list"]
        })
    ]

這樣就可以把home、detail、list三個js和css用到的公共模塊提取到common-app.chunk.js和common-app.chunk.css這兩個文件了。注意頁面要先引入這兩個文件,然后再引入具體頁面的js,webpack在common chunk里面定義了它的require函數。如上面的home.html:

    <script src="//develop.com/static/build/common-app.chunk.js"></script>
    <script src="//develop.com/static/build/home.js"></script>

可以指定一個minChunk的參數,指定模塊至少被require幾次才能提取出來,默認是3

還可以定義兩個commonChunk,例如在詳情頁、列表頁和首頁都有搜索的模塊,而其它頁面沒有搜索的模塊,也就是說除了所有頁面都有的公共模塊如登陸注冊外,還有一個搜索的公共模塊有三個頁面要用到。如果都用一個common chunk,會把搜索的也放進來,但其它很多頁面並不需要用到。這個時候需要加多一個common chunk:

    plugins: [
        new CommonsChunkPlugin({
            name: "search-app.chunk",
            chunks: ["search-app-init", "home", "detail", "list"]
        }),
        new CommonsChunkPlugin({
            name: "common-app.chunk",
            chunks: ["home", "detail", "search-map", "search-app.chunk", "sell", "about", "blog"]
        })
    ]

注意要把search-app.chunk也寫到下面那個所有頁面的chunk里面,否則webpack會定義兩個一樣的require函數,頁面的模塊也會跟着混亂,一刷頁面就報錯。頁面引用js的順序就變成了:

    <script src="//develop.com/static/build/common-app.chunk.js"></script>
    <script src="//develop.com/static/build/search-app.chunk.js"></script>
    <script src="//develop.com/static/build/home.js"></script>

壓縮和版本號

壓縮只需要要在plugins里面再添加一個用來壓縮的插件:

var webpack = require("webpack");
plugins: [
    new webpack.optimize.UglifyJsPlugin()
]

這樣執行webpack輸出的js/css就是壓縮的

版本號就是在輸出帶上hash的替換符,如下:

module.exports = {
    output: {
        path: "assets",
        publicPath: "/static/build/",
        filename: "[name]-[chunkhash].js",
        chunkFilename: "bundle-[chunkhash].js"
    },

    plugins: [
        new ExtractTextPlugin("[name]-[contenthash].css")
    ],
}

其中js用的是webpack的chunkhash,而css用的是contenthash,contenthash是根據內容生成的hash。如果不用contenthash,那么一改js,css的版本號也會跟着改變,這個就有問題了。webpack還有另外一個自帶的叫做"[hash]",這個hash是所有文件都用的同一個哈希,也就是說某個文件改了,所有文件的版本號都會跟着改,所以一般不用這個。

運行webpack,如果報了下面這個錯誤:

ERROR in chunk detail [entry]
[name]-[chunkhash].js
Cannot use [chunkhash] for chunk in '[name]-[chunkhash].js' (use [hash] instead)

那你就把plugins里面的熱替換插件注釋掉就好了,上線的config不需要熱替換:

    plugins: [
        //new hotModuleReplacementPlugin(),
    ],

成功執行后,就會在設定的output目錄下面輸出加上版本號的文件:

.
├── detail-d19e4614a1c4f3c1581b.js
├── home-11198f8526424e8c58ce10a2799793e3.css
└── home-5ec13a52eea2a6faf96a.js

有了版本號之后,下一步是要把html里面的js/css換成帶版本號的路徑

替換Html里js/css路徑

 之前在html里的路徑是test.com,現在要把它換成cdn且帶版本號的路徑,也就是說,目標是要把下面的引入:

<script src="//develop.com/static/build/home.js"></script>

替換成下面的引入,並把新生成的html輸出到built目錄

<script src="//cdn.mycdn.com/test/home-5ec13a52eea2a6faf96a.js"></script>

目測沒有現成符合格式的插件可以用,可以自已用node寫一個,不費事。

首先要知道所有文件的對應的版本號,可以用AssetsPlugin,生成source-map:

var AssetsPlugin = require('assets-webpack-plugin');
    output: {
        publicPath: "//cdn.mycdn.com/static/build/"
    },
    plugins: [
        new AssetsPlugin({filename: './source-map.json', prettyPrint: true}),
    ]

執行webpack之后,就會生成source-map.json,打開這個文件:

{
  "detail": {
    "js": "//cdn.mycdn.com/static/build/detail-c8a2c82ebe2e48e06564.js"
  },
  "home": {
    "js": "//cdn.mycdn.com/static/build/home-380af86bfeb6fcb477a4.js",
    "css": "//cdn.mycdn.com/static/build/home-11198f8526424e8c58ce10a2799793e3.css"
  }
}

根據develop.com開頭的以及最后面的home.js/home.css,就可以在上面找到對應的路徑名。筆者寫了個腳本,可以實現這個功能,詳見:version-control-replace-html

到這里,整個流程就基本完成了。還有一些優化的步驟

優化

1. 優化模塊id

 webpack對於每個模塊都是用id標志,而不是用模塊的名字,只是為了節省空間。還可以再節省,就是用它自帶的occurrence-order插件將最常用的模塊靠前,這樣可以再節省一點點空間,因為id是從0開始排的,從一位數到n位數。

new webpack.optimize.OccurenceOrderPlugin()

2. 移出版本號

在上面用了common-chunk的插件,抽離公共模塊,在這個common-chunk.js里,webpack會定義每個模塊加載的src,以便於加載那些需要動態加載的chunk,如下:

script.src = __webpack_require__.p + "" + chunkId + "-" + {"0":"0cb48ff1ab1d1156015d","5":"e9e7f761f306c648ccef","6":"cbbdf8e3ad1aba34ced0"}[chunkId] + ".js";

從上面可以看出它會把版本號也寫在里面,這樣就導致一個問題,每改一個js文件,它的版本號就會變化,就會導致common chunk里面的內容發生變化,所以它的版本號也得跟着變,也就是說改了一個文件,影響了兩個文件。所以需要把它抽出來,有個插件已經做了這樣的事情,叫做ChunkManifestPlugin

var ChunkManifestPlugin = require('chunk-manifest-webpack-plugin');
plugins: [
        new ChunkManifestPlugin({
            filename: "chunk-manifest.json",
            manifestVariable: "webpackManifest"
        })
]

傳兩個參數,一個是輸出文件名,另一個是變量名,用於上面的script.src,執行webpack后,它會把上面script.src的那一坨東西放到chunk-manifest.json,然后在頁面寫一個內聯的script,定義一個全局變量window.webpackManifest,值為manifest.json里面的內容。筆者已在上面的替換版本號的腳本做處理,只需在頁面合適的地方寫上一行:

<!--%webpack manifest%-->

就會把這行替換成一個script標簽。

3. 多個common-chunk的優化

 在上面寫了兩個common chunk,在生成的兩個chunk文件里面,你會發現大量的的重復代碼,已經失去了公共模塊的作用,這個問題可以用一個MoveToParentMergingPlugin解決,它會把search-app用到的common-app的模塊全部移到了common-app,search-app就不會重復common-app的內容了。

html保存自動刷新

 上面提到,只要一保存css/js,webpack-dev-server就會自動保存和刷新,但是html/jsp沒辦法(如果你用react開發,可以用react-hot-loader),其實可以手動解決這個問題。打開node_modules/webpack-dev-server/client/index.js這個文件,可以發現webpack是用的sockjs實現自動刷新的。瀏覽器使用sockjs創建socket客戶端,連接到webpack的服務,保存更改的時候,服務就向瀏覽器的socket發送消息,接收到這個消息后客戶端就調window.location.reload刷新頁面。所以可以模仿這個過程,在本地另開一個服務,監聽html的修改,然后向瀏覽器端發送刷新頁面的消息。

具體來說,首先在上面的node_modules/webpack-dev-server/client/index.js這個文件最后面再添加一個socket連接:

/*自定義reload window*/
var reload = new SockJS("http://localhost:9999/reload");
reload.onopen = function(){
    console.log("customer reload start.......");
}

reload.onclose = function(){
    console.log("customer reload close.......");
}

reload.onmessage = function(_msg){
    var msg = JSON.parse(_msg.data);
    if(msg.type === "reload"){
        console.log("customer reload window now");
        window.location.reload();
    }
}

這個9999端口的server就是下面要在本地監聽的一個socket服務。在開這個socket服務之前,需要先在本地開一個監聽文件修改的服務,然后再向這個socket服務發送消息。監聽的服務比較好寫,有現成的node包可以用:chokidar,使用也非常簡單。監聽到修改之后就可以執行上傳服務器的命令,然后(使用進程間的通信)再向socket服務發送一個需要刷新的消息,再傳遞給瀏覽器的scoket,如上面的代碼,一收到消息就刷新頁面。具體代碼查看github 

 

 除了優化,在使用中會遇到的一些問題:

解決問題

1. umd的require模式

 有時候會引入外部的庫,這些庫可能會用umd的require模式,判斷是要用requirejs還是commonjs或是寫個全局的函數:

    /* CommonJS */ if (typeof require === 'function' && typeof module === 'object' && module && typeof exports === 'object' && exports)
        module['exports'] = init(require("ByteBuffer"));
    /* AMD */ else if (typeof define === 'function' && define["amd"])
        define("lib/chat/ProtoBuf", ["./ByteBuffer"], init);
    /* Global */ else(global["dcodeIO"] = global["dcodeIO"] || {})["ProtoBuf"] = init(global["dcodeIO"]["ByteBuffer"]);

這個的問題就在於,只要頁面上有require出現,webpack就會去打包,不管你是寫if里面還click事件里面。因為像上面說的,webpack會把異步加載的文件打包成一個boundle文件,同時也會把非異步的打包到一起。像上面那樣寫,它會重復打包,生成好多個bundle。只要加多一個umdREquirePlugin,webpack就能正常打包了。

2. 如何加載外部資源

 webpack是一個打包的工具,它並不是像requireJs那樣可以支持直接require一個外部資源。

例如我要require谷歌地圖:https://maps.googleapis.com/maps/api/js,打包的時候webpack會給出一個warning,說加載不到這個外部資源,運行代碼的時候會報錯,提示沒有這個模塊。

另外一個問題是,我需要if else判斷,如果是中國的環境就加載中國域名的谷歌地圖:http://ditu.google.cn/maps/api/js 否則就加載上面的,使用webpack是沒辦法做到的, 使用requireJs就可以很簡單地直接require一下就行。

但其實這個問題很好解決只要自己寫一個動態加載script的函數就好了,一個兼容性很好的版本:

function loadScript(url, callback){
            var script = document.createElement("script")
            script.type = "text/javascript";
            if (script.readyState){  //IE
                script.onreadystatechange = function(){
                    if (script.readyState == "loaded" || script.readyState == "complete"){
                        script.onreadystatechange = null;
                        callback();
                    }
                };
            } else {  //Others
                script.onload = function(){ callback(); };
            }
            script.src = url;
            document.getElementsByTagName("head")[0].appendChild(script);
        }

詳見:The best way to load external JavaScript

 

webpack雖然是一個利器,但是坑也不少,目前遇到過的不太好解決的問題:

遇到的困難

1. chunkhash

 使用chunkhash有兩個問題,一個是css改變之后,js的版本號也會跟着改變,即使js沒有修改,但是比較這兩個js文件的時候,你會發現這兩個版本號不一樣的文件內容是完全一模一樣的。因為chunkhash不是根據文件內容算的hash值。第二個問題是,相同的代碼在不同人的機器上打的包的版本號不一樣。如果使用一些根據文件內容打版本號的插件,如webpack-md5-hash,這個插件是用文件內容作一個md5的計算得出一個版本號,這樣可以解決上面的兩個問題,但是又引發了新的問題,這個md5的時不時就會出現打的版本號不唯一的情況,文件內容不同、版本號相同,而且這個概率還不小。所以最后還是放棄了使用這個插件,然后又嘗試了另外一個使用sha算法計算,但是這個改了一個文件會使幾個文件的版本號也發生變化。現在還是使用chunkhash

2. 模塊id發生變化

上文提到,webpack的模塊是用id標志的,每個模塊對就一個id,例如util對應2,但是這個id不是固定不變的,在n次修改和打包之后,util的id可能會變成了3,這個就比較坑了,給增量上線造成了阻力,即單獨上一個html有風險。因為在common-chunk里面,util的id是上次打包的時候定的,但是你這次打包util的id變了,而你只想上home.html,在home.html里面引的home.js里面使用到的util的id對不上common-chunk里面的,導致不能在home里面正常地加載util這個模塊。一個臨時的解決辦法是,home.js不要使用common-chunk,所有的模塊都打包到home.js里面就不會有這個問題。

 

綜上對於webpack的介紹基本說完了,后續會繼續研究webpack的打包方式和怎么樣寫一個webpack的插件。如果上面有什么不合理或可以優化的地方還請指出。

 

個人博客:http://yincheng.site/webpack


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM