webpack
的流行給前端開發減小了許多沒必要要的工做,webpack
可讓咱們更純粹的關注咱們的代碼,可是不少人認爲它更適合單頁應用,主要有如下一些痛點javascript
seajs
、requireJs
等)其實第二點我已經在上篇文章中講過了,若是平滑的過渡到webpack
,痛點一也解釋過,只是沒有詳細的說明,這次分享一個完整的配置,來應對你的多頁項目。不論是jsp
、php
、html
、xshtml
均可以經過具體的配置來使用webpack
,爲何如此青睞webpack
,在我看來熱更新技術、less
、sass
、es6
、es7
的引入是最吸引個人(嘗試過使用gulp
、可是感受並無webpack
這種一站式服務來得順手),下面我詳細講述下下面一些配置的用途,部分代碼來自vue-cli。php
├─build // webpack的配置文件存放目錄 ├─Public // 咱們的前端資源存放目錄 │ ├─dev // 源碼存放目錄(能夠更名爲src) │ │ ├─css // 一些共用的css文件,共用才放這裏哦 │ │ ├─font // 字體文件 │ │ ├─images // 圖片文件 │ │ └─js // js文件 │ │ ├─libs // npm裏沒有的第三方插件或庫 │ │ ├─modules // 項目的業務組件存放目錄 │ │ └─page // 頁面的目錄 │ │ └─Index // 具體的頁面名稱 │ └─dist // 編譯後的存放目錄 └─static // 好像是拿來緩存文件用的?vue-cli存在的
固然,我目前開發的項目是半路引入webpack
的,大部分都仍是jQuery
那套東西、可是我仍是秉着關注點分離的原則,將html
、css
、js
按頁面來放了,再也不使用老掉牙的按文件類型來放、那是由於有了webpack
的打包才能夠這麼隨意。除了分離出來的模板(ThinkPHP
用<include file=""/>
標籤來引入模板)文件,js和css都是放到同模板名的Public/dev/js/modules目錄裏了,這樣一來能夠直接像這樣css
require( './style.less' ); ...
先在js文件的頭部引入這個組件的樣式文件,再來寫js代碼,至少咱們在使用組件的時候沒必要關心css了(下篇文章會講講重構後如何連html也不關注了)html
這裏爲何會有一個images
目錄看起來不少餘呢,那是由於咱們的php模板裏的圖片標籤src
前面都帶了一個php
的系統變量,webpack
插件的靜態分析是沒法識別這裏的路徑的,因此保留了這個目錄,在打包後用插件拷貝到打包目錄裏前端
而後是page
這個目錄,這個目錄是拿來存放咱們頁面的三劍客的,好比有一個叫index
的目錄,裏面有css
、js
、html
文件,這裏的index
能夠看做是一個頁面目錄,也能夠看做是一個分類,若是是分類,那下面就應該是頁面了,html裏不該該引用css
文件和js
文件,由於webpack會幫咱們插入生成新的html到咱們指定的目錄裏vue
最重要的就是build
目錄下的了java
proxyTable
項我已經在上篇文章中講過了,這裏就不贅述了webpack
這個文件就是描述咱們entry
也就是入口文件和html模板之間的關係映射的文件的git
module.exports = { // 微知首頁 'Index': { // 對應到Public/dev/js/page的文件夾名稱 file: 'main', // 視圖層的文件名稱,默認爲index viewFile: 'index', disable: false, templateOutput: 'Index' }, 'EditText': { chunks: [ 'editor' ], disable: false }, // 編輯模板 'Template': { chunks: [ 'editor' ], disable: true }, // 默認模板 'GzhArtStyle': { chunks: [ 'editor' ], disable: true } };
這裏導出的每一個對象的鍵值都對應了page
目錄裏的名字,下面的file
字段對應的入口js文件名稱,默認爲main
,viewFile
對應的是html模板名稱,默認爲index
,這裏頗有用,由於在ThinkPHP
的View
目錄裏模板部分文件夾的,因此咱們配合templateOutput
把html輸出過去就不存在目錄了,templateOutput
的默認值爲這個對象的鍵值如Index默認爲Index。disable
字段是開發模式使用的,當運行npm run dev
命令時會自動掃描這個字段,若爲false
纔會啓動,若是所有都爲false,那麼你頁面越多形成性能開銷就越大,因此除非你同時去開發幾個頁面,這裏建議啓動的頁面不超過5個,其餘頁面若要運行,提早npm run build
一次讓它跑編譯後的代碼就行了。chunks
字段是用來標記當前頁面依賴的除了共有chunks
須要依賴的其餘chunks
,上面的有chunks字段的三個頁面都是引用了百度編輯器,由於百度編輯器的包都太大了,因此不建議抽取到公用的chunk裏,這裏的配置在webpack.prod.cfg.js
文件裏有單獨配置。es6
這個文件主要是getHtmlWebpackPlugins
方法,配合註釋您就能看懂剛纔的mapping配置都怎麼用的了
exports.getHtmlWebpackPlugins = ( rename ) => { let HtmlWebpackPlugins = []; Object.keys( mapping ).forEach( function( name ) { // 若是不是開發環境 就所有打包 // 若是是開發環境 就根據disable來進行打包 ( process.env.NODE_ENV !== 'development' || !mapping[ name ].disable ) && HtmlWebpackPlugins.push( new HtmlWebpackPlugin( { alwaysWriteToDisk: true, // php端使用到的模板 // 若是是其餘目錄在此修改路徑 filename: `${ROOT}/Application/Home/View/${mapping[ name ].templateOutput ? mapping[ name ].templateOutput : name}/${mapping[name].viewFile || 'index'}.html`, // 插件用的模板文件 template: `${ROOT}/${config.$d}/js/page/${name}/${mapping[name].viewFile || 'index'}.${mapping[name].templateType || 'html'}`, chunks: ( function() { if ( !rename ) { //let chunks = [ 'vendor.npm', 'vendor.TP', 'manifest', 'vendor.modules' ]; let chunks = [ 'vendor.modules', 'vendor', 'manifest' ]; if ( mapping[ name ].chunks ) { chunks = chunks.concat( mapping[ name ].chunks ); } return chunks; } return []; }() ).concat( [ `${rename ? config.dev.entryPrefix : ''}${name}` ] ), // 手工排序 chunksSortMode: 'manual', inject: true, showErrors: false } ) ); } ); return HtmlWebpackPlugins; }
alwaysWriteToDisk
這個字段是咱們能先後端結合開發的關鍵,沒有使用後端模板的項目真的作到先後分離時是不須要這個字段的,由於PHP會讀這個文件再渲染數據出來給瀏覽器
都是些老生常談的配置,這裏就不贅述了。值得注意的是dev.client.js
這個文件被我刪了,由於使用了alwaysWriteToDisk
實時寫入的功能,改變css文件和js文件都會強制刷新,那熱更新徹底就無法用了,因此html文件的變化仍是須要手動刷新的
HtmlWebpackPlugin
這個插件確實是有多少頁面就要插入多少個實例進去的,因此直接
...utils.getHtmlWebpackPlugins( false ),
展開這個數組就行了,這裏傳入的布爾參數是爲了區分開發模式和build模式,傳入true
只會有一個chunk被包含進來,就是當前頁面依賴的全部js和css等
而後是chunks
有的頁面由於太簡單並無依賴太多共用的js,可是依賴了共用的css,因此這個chunk僅僅是爲了抽取css文件用,形成引用了一個空的js,暫時沒有想到好的解決辦法,歡迎再issues提出改進建議
這個chunk是爲了抽取咱們本身寫的業務組件、在修改業務組件後可以很好的利用緩存只更新這一個文件
上文mapping
裏的chunks字段就是這裏配置的,若是還有其餘局部共用的大chunk能夠在這裏再配置一個
vendor就是拿來放置第三方插件的,這裏抽取了npm和lib裏面的,當項目穩定後處於一個穩定的維護期,沒有較大改動時,這個文件就能夠長期緩存在用戶的電腦裏了。
new CopyWebpackPlugin( [ { from: path.resolve( __dirname, `../${config.$d}/images` ), to: `${config.build.assetsSubDirectory}/images`, ignore: [ '.*' ] } ] ),
上面的代碼就是拷貝images這個目錄到咱們打包生成的目錄裏,防止資源丟失的問題
這個腳手架極可能沒法直接運行在你的項目裏,可是能爲你的多頁入口的website
提供一個很好的引入webpack
的思路