webpack 只適合SPA嗎?
如果項目有50個的頁面想使用webpack,有成熟工具鏈嗎?
I"m Sean Larkin (@TheLarkInn), one of the maintainers of webpack!
For my full time job, we use a server-routed and rendered PHP and Vue.js (front end) stack.
Although CommonsChunkPlugin can be used to automatically extract multiple access shared modules, you should take care how you assign shared code across multiple entries.
For example, if 5 legacy pages use jQuery, but the other 45 pages do not, using CommonsChunkPlugin in its default state would essentially force a shared bundle on every page that would include jQuery.
I might recommend a plugin that can help your server side language consume these generated scripts.
https://github.com/mutualofomaha/multipage-webpack-plugin
This plugin will take every entry point defined in your entry object, and treat it as a standalone entry. In addition to this, it will also run html-webpack-plugin behind the scenes and emit a "template" for every single page.
For our use case ( https://github.com/mutualofomaha/multipage-webpack-plugin/tree/master/examples/multiple-nested-entries ), we create ".twig" partials that other ".twig" files consume based on convention.
Hopefully this helps, and sorry for speaking in english I currently do not know enough chinese/mandarin to be of use without english.
利用 CommonsChunkPlugin 可以自動提取多個入口共享的模塊:https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
我現在的項目使用了 webpack,算是部分單頁(偽單頁應用),各種頁面加起來需要二十多個入口文件,沒找到專門針對這種情況的成熟工具鏈,不過還是分享一下做法。
entry:- 所有入口文件維護在一個 entry-list.js 裡面,在 webpack 配置文件中 require("xxx/entry-list.js") 當做 entry 數組就好了。並且約定了所有入口(entry)文件都命名為 xxx.entry.js,每個 xxx.entry.js 會打包成一個 xxx.bundle.js。
- 公共的 js 文件打包為一個 vendor.js,這個 vendor 的組成是一個固定的數組,也就是手工指定的幾個模塊。
- 之所以不用 webpack 插件自動分析並提取公共部分,是因為只要有一個 xxx.entry.js 不使用某個模塊,這個模塊就不會被提取。對於一個大的模塊,這樣會使得每個 xxx.bundle.js 增大很多,而每個頁面的 xxx.bundle.js 是不同的,不利於緩存命中。
目前正在用 webpack + Vue 做多頁面。
- 多 entries
- 加上 CommonsChunkPlugin
- 使用 Vue standalone build
後台是 Rails,總體感覺還行。
對於用webpack管理多個頁面,我很有經驗。
因為我也和你一樣被這個痛點所折磨於是我自己寫了一個用起來很爽的plugin,現在把 web-webpack-plugin 分享給大家。
它補足了webpack的一些缺陷,比如對HTML的處理,它可以讓你以HTML文件為入口自動的分析出HTML依賴的資源輸出用於可直接在瀏覽器里運行的HTML。大概使用如下:
webpack配置
module.exports = {
entry: {
A: "./a",
B: "./b",
},
plugins: [
new WebPlugin({
filename: "index.html",
// html模版文件路徑(相對於webpack.config.js的完整路徑)
template: "./template.html",
requires: ["A", "B"],
}),
]
};
html模版 通過html模版你可以很方便清晰的描述資源應該注入的位置
&
&
&
&
&
&
&
&
&
&
&
&
&
&
&
&
- 在html模版里通過& 引入需要的entry,src="B" 中的B為chunk配置的名稱
- 注釋& 代表除開通過&引入的資源外,在 requires 里配置的剩下的依賴的資源應該被注入的地方,如果模版沒有出現&就放在body標籤的最後
輸出的html:
&&
&
&
&
&
&
&
&
&
&
&
&
&
&
&
針對每一個html依賴的資源,有如下屬性可以配置:
- _dist 只有在生產環境下才引入該資源
- _dev 只有在開發環境下才引入該資源
- _inline 把該資源的內容潛入到html里
- _ie 只有IE瀏覽器才需要引入的資源,通過 [if IE]&>resource&
對與你說的50個頁面也非常好辦:
AutoWebPlugin 可以找到一個目錄下所有的頁面入口,自動為所有的頁面入口配置一個WebPlugin輸出對應的html,使用如下:
module.exports = {
plugins: [
new AutoWebPlugin("./src/", {
// 所有頁面公用的模版
template: "./src/template.html",
// 提取所有頁面公共的代碼
commonsChunk: {
name: "common",
minChunks: 2,
},
}),
]
};
源代碼目錄結構
── src
│ ├── home
│ │ └── index.js
│ ├── ie_polyfill.js
│ ├── login
│ │ └── index.js
│ ├── polyfill.js
│ ├── signup
│ │ └── index.js
│ └── template.html
輸出的目錄結構
├── dist
│ ├── common.js
│ ├── home.html
│ ├── home.js
│ ├── ie_polyfill.js
│ ├── login.html
│ ├── login.js
│ ├── polyfill.js
│ ├── signup.html
│ └── signup.js
AutoWebPlugin插件找出了./src/目錄下所有的目錄home login signup,針對這3個目錄分別讀取目錄里的index.js作為入口,生成三個html文件home.html login.html signup.html
更多功能和用法見文檔 gwuhaolin/web-webpack-plugin
管理多個單頁應用demo gwuhaolin/web-webpack-plugin
我在項目中多處遇到了和你一樣的問題,對此我想分享給大家我的
webpack相關的經驗總結
- webpack原理與實戰 webpack原理與實戰 · Issue #4 · gwuhaolin/blog
- webpack2 終極優化 webpack2 終極優化 · Issue #2 · gwuhaolin/blog
- 快速優雅的為React組件生成文檔 快速優雅的為React組件生成文檔 · Issue #1 · gwuhaolin/blog
如果你喜歡的話賞個贊鼓勵下我,我會把它做的更好。
我的習慣是用webpack只包js。(其實什麼都能包,分包直接寫多個entry就好) chunkplugin 是好東西。
網頁的入口總是設置為html 然後load js。 css是自己幾個小包。
看似是分頁的網站。其實是多個spa。每頁按自己的router工作。 有獨立的,也有共享的js。
反正總是要server render的。每頁線上的js只展示些大件,效果,處理數據什麼的。看似複雜,包完了並不大。沒用的不要包進去就好了。fs 讀取入口 js 當做 entry,然後 htmlwepackplugin 當做頁面配置,commonchunkplugin 來提取公共部分。當然編譯速度就看你的提取情況了,常用的全局用下 external,其他隨意,我目前是這樣乾的,開發了 15 個左右模塊了,沒撒問題。不過我沒有用 htmlwepackplugin ,我覺得太麻煩了, version 還是手動配置了一下,你嘗試做做就知道了。然後 mainfest 這種用上的話還是自動編譯頁面生成 hash version 比較好。
webpack 只是模塊化的工具了,怎麼用都是可以的,多頁面可能要加點約定和編程配置更好用點。單頁只是現在教程泛濫的原因,大家 copy 來 copy 去~認真體會工具真正乾的事情就會好很多,針對業務和場景去合理的使用工具。
知乎評論系統藥丸
@Sean Larkin I translate your answer to Chinese. If you will, you could append them to your answer. Here they are:
我是Sean Larkin (@TheLarkInn), webpack的一名維護者!在我的全職工作中,我們使用了一個服務端控制以及渲染的基於PHP以及Vue.js(前端部分)的技術棧。 儘管CommonsChunkPlugin可以被用於自動提取多次訪問的共享模塊,然而你還是應該關心你如何在多個入口分配共享的代碼。 舉個例子, 如果5箇舊頁面用了jQuery, 但是另外的45個頁面沒有使用,在插件摸默認的狀態下使用CommonChunkPlugin基本上就是強制每個頁面的一個共享代碼包(a shared bundle)包括jQuery。 我會推薦一個可以幫助你們服務端語言使用這些生成腳本的插件。https://github.com/mutualofomaha/multipage-webpack-plugin 這個插件會使用每個你在entry對象定義的入口點,然後把它視為一個獨立的入口。除此以外,它會秘密地運行html-webpack-plugin以及為每一個頁面發送"模板"。 在我們的用例中( https://github.com/mutualofomaha/multipage-webpack-plugin/tree/master/examples/multiple-nested-entries ), 我們基於約定創建了".twig"片段以及其他的".twig"文件來使用。 希望這些可以有幫助,以及為我使用英語而抱歉,我現在對中文/官話還是懂得不多以至於我無法在使用它們的時候不用英語。
不是啊,多頁面就是配置多個 entry 而已
可以參考 教你一步步從零構建webpack開發多頁面環境 · Issue #27 · riskers/blog我司就在用,方案樓上都說到了,多entry和CommonsChunkPlugin。
說多entry的都想得太簡單了,正如樓上所說,多entry,就意味著無論多少個頁面,每次打線上包或者本地調試時都要全部打一遍,這根本沒道理講不通!
我們公司針對這種非SPA項目採用的方案是,將webpack配置拆開,不變動的部分共用,變動的部分(也就entry啦,以及plugins等不一樣等)寫進一個conf文件(json格式)放入各個頁面的根目錄,同時在這個根目錄會放入package.json(用來執行npm打包命令), 這樣npm run start後,自動實時生成一份webpack配置文件,然後執行打包或者編譯任務, 每個子頁面都是獨立的打包過程,
這一套方案解決的痛點是,webpack配置文件不用重複編寫,目錄結構不用重複搭建,真正做到了一次搭建,多次復用,目前在公司運行一年多,非常高效、成熟
PS: 等有時間我開源把方案放到github上
@Sean Larkin 已經說的很好了,webpack其實不關心你是SPA還是多頁面,對它而言萬物皆資源,只要可以歸類到資源的它都能幫到我們,多頁面無非就是多個SPA,稍微複雜點的就是多頁面之間的資源共享,盡量避免多個依賴重複載入的情況,這個webpack也幫我們處理了
CommonsChunkPlugin可以幫我們提取公用模塊
HtmlWebpackPlugin可以幫我們提取多個頁面入口
HashedModuleIdsPlugin可以幫我們穩定module ID
manifest可以幫我們來實現長效緩存
所以多頁面不是問題,具體的可以看我寫的一個支持多頁面和單頁面的模板shaodahong/wdemo
介紹文章在這boarder,快速開始一個webpack項目-優化篇 · Issue #8 · shaodahong/dahong
問題是那麼多的頁面一起打包,webpack 會直接內存爆掉。我們的項目最多的時候有70多個頁面,一起打包經常把 webpack 搞掛。當然後面我們也總結了一套打包多個頁面的經驗,只能說搬個小板凳坐等我的同事們來分享經驗了。
一般來說,應用代碼是不會很大的,common代碼的提取也多是針對基礎庫而言.
所以用ignore插件去掉基礎庫後,加cdn的形式也是個不錯的選擇.
推薦閱讀:
※能否用通俗語言講一下web前端講的「切圖」到底是什麼意思?
※js等語言的undefined值存在的意義是什麼?
※npm install的實現原理?
※移動端前端開發與PC端比有哪些不同?
※jQuery真的過時了嗎?