webpack+vue 實現多頁面開發
首先,要大概知道webpack是什麼,webpack的外掛都是做什麼用的,vue是什麼,然後看完之後也可以去補充一下這些方面的知識。
第一步:安裝環境
需要安裝的有:
- nodejs,並新增入環境變數PATH
- 使用nodejs安裝webpack和webpack-dev-server
參考內容:
http://webpack.github.io/docs/tutorials/getting-started/
使用命令:
npm install webpack -g
之所以要在全域性安裝webpack是因為使用webpack的命令列方便,不需要在每一個專案中到node_module中呼叫。 - Atom編輯器
這個從網上下載,
第二步:建立專案模板
vue init wepack vue-multipage-demo
- 1
- 1
如上所示,這條命令的意思是使用vue的init命令,建立一個基於webpack元件化管理的專案。這將會在D:\WS_WebStorm目錄下建立新目錄vue-multipage-demo。
圖2
如圖2,在經過設定之後,可以看到已經生成了一個專案vue-multipage-demo,接下來需要切換到專案目錄下進行操作。在資源管理器中,我們可以看到已經生成了這樣的目錄:
圖3
如圖3,各個資料夾和檔案分別是:
build webpack構建過程的設定檔案,包括除錯和釋出版本以及一些工具函式
config 這裡是webpack-dev-server的一些設定,關於webpack和webpack-dev-server的設定,詳見官方文件
src 專案的原始檔所在,按照你需要的樣子寫js和html檔案,webpack將打包成瀏覽器可識別的,如ES6
static 這裡是存放靜態資源的地方,在build之後會生成dist資料夾,這個資料夾中的檔案會原封不動放進去
.babelrc webpack外掛babel的設定
.editorconfig 這是atom編輯器生成的配置檔案,在各個專案中可以自由配置
.eslintignore 使用eslint檢測程式碼是否符合規則的忽略目錄,用於eslint設定
.gitignore 使用
index.html 專案生成後的入口頁面,因為vue預設是使用單頁面的,所以在webpack中同時也只有這一個入口
package.json nodejs的配置
README.md 說明檔案,其中說明了使用vue-cli建立專案之後應該怎麼做
dist build之後生成的目錄,其中存放webpack打包之後的結果,webpack中需要指定build規則
表1
圖4
如圖4,執行這兩條命令,切換到專案目錄下,使用npm的安裝命令,對已經生成的package.json所依賴的元件進行安裝。當然,我們之後還會安裝一些其他的外掛。
第三步:補充需要的外掛
雖然說,在專案開發中,外掛的補充是根據需求進行增減的,但是在這個專案中,有一些基本的需要新增的外掛,我在這裡提出。package.json中的程式碼如下:
"dependencies": {
"babel-runtime": "^6.0.0",
"bootstrap": "^3.3.7",
"bootstrap-table": "^1.11.0",
"font-awesome": "^4.6.3",
"jquery": "^3.1.0",
"node-glob": "^1.2.0",
"vue": "^1.0.21",
"vue-resource": "^0.9.3"
},
"devDependencies": {
"babel-core": "^6.0.0",
"babel-eslint": "^6.1.2",
"babel-loader": "^6.0.0",
"babel-plugin-transform-runtime": "^6.0.0",
"babel-preset-es2015": "^6.0.0",
"babel-preset-stage-2": "^6.0.0",
"babel-register": "^6.0.0",
"bootstrap-loader": "^2.0.0-beta.9",
"connect-history-api-fallback": "^1.1.0",
"css-loader": "^0.23.0",
"dynamics.js": "^1.1.5",
"eslint": "^2.10.2",
"eslint-config-standard": "^5.1.0",
"eslint-friendly-formatter": "^2.0.5",
"eslint-loader": "^1.3.0",
"eslint-plugin-html": "^1.3.0",
"eslint-plugin-promise": "^1.0.8",
"eslint-plugin-standard": "^1.3.2",
"eventsource-polyfill": "^0.9.6",
"express": "^4.13.3",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.8.4",
"function-bind": "^1.0.2",
"html-webpack-plugin": "^2.8.1",
"http-proxy-middleware": "^0.12.0",
"json-loader": "^0.5.4",
"ora": "^0.2.0",
"shelljs": "^0.6.0",
"url-loader": "^0.5.7",
"vue-hot-reload-api": "^1.2.0",
"vue-html-loader": "^1.0.0",
"vue-loader": "^8.3.0",
"vue-style-loader": "^1.0.0",
"webpack": "^1.13.2",
"webpack-dev-middleware": "^1.4.0",
"webpack-hot-middleware": "^2.6.0",
"webpack-merge": "^0.8.3"
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
其中包括了由專案自動生成的一些外掛。
我梳理一下,主要有下面這些,其中標註紅色的是我自己用來開發依賴的:
dependencies:
babel-runtime
bootstrap
bootstrap-table
font-awesome
jQuery
node-glob
vue
devDependencies:
bootstrap-loader
dynamics.js
那麼主要就是新增一下node-glob和vue,其他的如果需要再進行新增。nodej-glob是用來獲取路徑的,vue是需要依賴的主要部分。
第四步:修改專案
這一步最重要。
在我們沒有動過之前,src目錄是這個樣子的,如圖5:
圖5
首先,建立如下目錄結構:
src
|
—–module
|
—–index
|
—–index.html
—–main.js
將之前外面的index.html放進來,main.js放入index,改名為index.js,此處一定注意名稱要相同,否則後面尋找路徑時是找不到對應檔案的。然後將App.vue放入components。最後是這樣的,如圖6:
圖6
這時候需要對檔案進行一定的修改。首先是index.js,對App的呼叫,路徑修改,如圖7
圖7
修改完了上面的資源,我們要修改webpack的配置。
我們介紹一下webpack在這個專案中原本的順序:由於webpack將所有的js,css/less,html等都視為js的可引入資源,所以入口就成了js檔案。那麼webpack需要設定一個入口的js檔案,這個入口的js檔案就是main.js,在webpack中有一個外掛,叫做html-webpack-plugin,這個是用來將js和html對應起來,也就是若干js對應一個html,在原來的專案中html就是index.html。
在執行npm run dev 或者build之後,就會將檔案打包,由於dev的時候檔案是在記憶體中,所以build可以看得比較清楚,在dist目錄中,會有一個index.html,其中已經打包進了
webpack.base.conf
新增下面兩行在這裡,圖8中位置,
var glob = require('glob');
var entries = getEntry('./src/module/**/*.js'); // 獲得入口js檔案
- 1
- 2
- 1
- 2
圖8
這裡的glob,就是前面提到的node-glob。將entry修改為這個,圖9中位置,
圖9
然後在下面新增getEntry方法。
function getEntry(globPath) {
var entries = {},
basename, tmp, pathname;
glob.sync(globPath).forEach(function (entry) {
basename = path.basename(entry, path.extname(entry));
tmp = entry.split('/').splice(-3);
pathname = tmp.splice(0, 1) + '/' + basename; // 正確輸出js和html的路徑
entries[pathname] = entry;
});
console.log("base-entrys:");
console.log(entries);
return entries;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
因為我們的想法是要將所有的業務模組放在module中,這樣一來的話,就在module中細分,最後輸出html都在dist的module下。這裡的字串操作也是和路徑的情況相匹配的,如果有需要進行其他方式的設定,注意在這裡修改路徑的識別。
webpack.dev.conf.js
在開啟後,我們會發現在這裡有一個外掛的設定,如圖10:
圖10
這個 外掛就是剛才提到的將輸出html頁面build結果的地方。
首先,新增
var path = require('path');
var glob = require('glob');
- 1
- 2
- 1
- 2
用來引入path和glob工具。
將圖10中的那一段去掉,因為我們要自己來新增這個外掛。
同樣的,在這個檔案中也需要新增這個函式,放在檔案的下面,
function getEntry(globPath) {
var entries = {},
basename, tmp, pathname;
glob.sync(globPath).forEach(function(entry) {
basename = path.basename(entry, path.extname(entry));
tmp = entry.split('/').splice(-3);
pathname = tmp.splice(0, 1) + '/' + basename; // 正確輸出js和html的路徑
entries[pathname] = entry;
});
console.log("dev-entrys:");
console.log(entries);
return entries;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
然後再新增這一段,
var pages = getEntry('./src/module/**/*.html');
console.log("dev pages----------------------");
for (var pathname in pages) {
console.log("filename:" + pathname + '.html');
console.log("template:" + pages[pathname]);
// 配置生成的html檔案,定義路徑等
var conf = {
filename: pathname + '.html',
template: pages[pathname], // 模板路徑
minify: { //傳遞 html-minifier 選項給 minify 輸出
removeComments: true
},
inject: 'body', // js插入位置
chunks: [pathname, "vendor", "manifest"] // 每個html引用的js模組,也可以在這裡加上vendor等公用模組
};
// 需要生成幾個html檔案,就配置幾個HtmlWebpackPlugin物件
module.exports.plugins.push(new HtmlWebpackPlugin(conf));
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
這個同樣是通過指定的路徑,按照我之前的預想,進行html的迭代獲取,然後對每一個html進行設定。我們的多頁面輸出關鍵也就在這個地方。
html-webpack-plugin這個外掛可以為一個html輸出打包對應的js模組。chunks就是對應的js模組,也就是webpack的入口,包括entries和使用了webpack.optimize.CommonsChunkPlugin外掛聲稱的公共js模組。這些模組都有各自的名字,entries的名字就是前面通過getEntry函式生成的一組入口元件名稱和路徑。
通過上面的修改,就做成了這樣一件事情:為webpack提供多個js入口,而這些js入口和html頁面是在同一個資料夾下的,那麼它們的key或者說name就是相同的。這樣在迴圈的時候,就會獲取到對應的js和html,通過迴圈建立多個html-webpack-plugin來將不同的js模組打包進對應的html,並通過webpack批量構建,在dist中就會產生我們需要的一組html檔案。而這些html檔案都是已經經過壓縮的,js程式碼也經過了壓縮處理。
webpack.prod.conf.js
和webpack.dev.conf.js中做類似的處理,先註釋掉原來的HtmlWebpackPlugin,然後在下面新增函式,通過迭代插入多個HtmlWebpackPlugin。
HtmlWebpackPlugin更多的設定,到webpack的官網上檢視。
然後使用npm run dev或者npm run build來構建。在構建的過程中,可能會出現一些依賴外掛不存在的錯誤,需要先使用npm install –save-dev 外掛名 來安裝相應的依賴外掛。
這樣,index.html就被構建到了dist/module/index.html中。
但功能是一模一樣的。
vue的使用在這裡不贅述。這裡說明一下,我們的module中,是系統的業務模組,components中是功能模組和細分的程式碼模組,也就是vue元件。由於webpack這裡帶了babel,所以在js原始檔中可以使用ES6的寫法。在業務js中,就可以通過匯入,組合,自定義vue元件,來實現相應的業務需求。
其他
比如在我現在拆分的這個網頁中,包括這麼幾個部分:
這是對一個bootstrap網站模板index頁面進行拆分後的結果,css,html都放在對應的vue中,當然,我也引入了jquery。
vue的元件可以實現繼承和mixin。能夠很好的進行元件化開發,而通過webpack將src的原始碼進行構建變成瀏覽器能夠識別的正常檔案。這樣就大大降低了前端開發的重複性。