按以下步驟可正常配置多頁面架構
記得安裝 node-glob 安裝命令:npm install node-glob --save-dev
文件附加
webpack.base.conf.js --參考more start 處

var path = require('path') var utils = require('./utils') var config = require('../config') var vueLoaderConfig = require('./vue-loader.conf') var webpack=require('webpack'); //加入webpack對象 //more var glob = require('glob'); //node-glob var entries = getEntry('./src/views/**/*.js'); // 獲得入口js文件. views替換了module //more end function resolve (dir) { return path.join(__dirname, '..', dir) } 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:",entries); return entries; } module.exports = { entry:entries , // entry: { // app: './src/main.js' // }, output: { path: config.build.assetsRoot, filename: '[name].js', publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath }, resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), 'basecommon':'./../../../common',//base組件引入公共樣式 'components':'./../components',//非base組件,./../common 'api':'./../../api',//非base組件 'base':'./../base' //非base組件引入base組件 } }, module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: vueLoaderConfig }, { test: /\.js$/, loader: 'babel-loader', include: [resolve('src'), resolve('test')] }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('images/[name].[hash:7].[ext]') } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('fonts/[name].[hash:7].[ext]') } } ] }, plugins: [ new webpack.ProvidePlugin({ $:"jquery", jQuery:"jquery", "windows.jQuery":"jquery" }) ] }
webpack.dev.conf.js --參考more start 處

var utils = require('./utils') var webpack = require('webpack') var config = require('../config') var merge = require('webpack-merge') var baseWebpackConfig = require('./webpack.base.conf') var HtmlWebpackPlugin = require('html-webpack-plugin') var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') //more var path = require('path'); var glob = require('glob'); //more end // add hot-reload related code to entry chunks Object.keys(baseWebpackConfig.entry).forEach(function (name) { baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) }) 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:",entries); return entries; } //more end module.exports = merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) }, // cheap-module-eval-source-map is faster for development devtool: '#cheap-module-eval-source-map', plugins: [ new webpack.DefinePlugin({ 'process.env': config.dev.env }), // https://github.com/glenjamin/webpack-hot-middleware#installation--usage new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin(), // https://github.com/ampedandwired/html-webpack-plugin // new HtmlWebpackPlugin({ // filename: 'index.html', // template: 'index.html', // inject: true // }), new FriendlyErrorsPlugin() ] }) //more start 先定義后插入 var pages = getEntry('./src/views/**/*.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)); }
webpack.prod.conf.js --參考more start 處

var path = require('path') var utils = require('./utils') var webpack = require('webpack') var config = require('../config') var merge = require('webpack-merge') var baseWebpackConfig = require('./webpack.base.conf') var CopyWebpackPlugin = require('copy-webpack-plugin') var HtmlWebpackPlugin = require('html-webpack-plugin') var ExtractTextPlugin = require('extract-text-webpack-plugin') var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') //more var path = require('path'); var glob = require('glob'); //more end var env = config.build.env var webpackConfig = merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }) }, devtool: config.build.productionSourceMap ? '#source-map' : false, output: { path: config.build.assetsRoot, filename: utils.assetsPath('js/[name].[chunkhash].js'), chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') }, plugins: [ // http://vuejs.github.io/vue-loader/en/workflow/production.html new webpack.DefinePlugin({ 'process.env': env }), new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false }, sourceMap: true }), // extract css into its own file new ExtractTextPlugin({ filename: utils.assetsPath('css/[name].[contenthash].css') }), // Compress extracted CSS. We are using this plugin so that possible // duplicated CSS from different components can be deduped. new OptimizeCSSPlugin({ cssProcessorOptions: { safe: true } }), // generate dist index.html with correct asset hash for caching. // you can customize output by editing /index.html // see https://github.com/ampedandwired/html-webpack-plugin /* new HtmlWebpackPlugin({ filename: config.build.index, template: 'index.html', inject: true, minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true // more options: // https://github.com/kangax/html-minifier#options-quick-reference }, // necessary to consistently work with multiple chunks via CommonsChunkPlugin chunksSortMode: 'dependency' }),*/ // split vendor js into its own file new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: function (module, count) { // any required modules inside node_modules are extracted to vendor return ( module.resource && /\.js$/.test(module.resource) && module.resource.indexOf( path.join(__dirname, '../node_modules') ) === 0 ) } }), // extract webpack runtime and module manifest to its own file in order to // prevent vendor hash from being updated whenever app bundle is updated new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', chunks: ['vendor'] }), // copy custom static assets new CopyWebpackPlugin([ { from: path.resolve(__dirname, '../static'), to: config.build.assetsSubDirectory, ignore: ['.*'] } ]) ] }) if (config.build.productionGzip) { var CompressionWebpackPlugin = require('compression-webpack-plugin') webpackConfig.plugins.push( new CompressionWebpackPlugin({ asset: '[path].gz[query]', algorithm: 'gzip', test: new RegExp( '\\.(' + config.build.productionGzipExtensions.join('|') + ')$' ), threshold: 10240, minRatio: 0.8 }) ) } if (config.build.bundleAnalyzerReport) { var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin webpackConfig.plugins.push(new BundleAnalyzerPlugin()) } module.exports = webpackConfig //more start 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("pro-entrys:",entries); return entries; } var pages = getEntry('./src/views/**/*.html'); console.log("pro 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, collapseWhitespace: true, removeAttributeQuotes: true }, inject: 'body', // js插入位置 chunks: [pathname, "vendor", "manifest"], // 每個html引用的js模塊,也可以在這里加上vendor等公用模塊 // necessary to consistently work with multiple chunks via CommonsChunkPlugin chunksSortMode: 'dependency' }; // 需要生成幾個html文件,就配置幾個HtmlWebpackPlugin對象 module.exports.plugins.push(new HtmlWebpackPlugin(conf)); }
-----------------橫線內為轉的-----------------------
首先,要大概知道webpack是什么,webpack的插件都是做什么用的,vue是什么,然后看完之后也可以去補充一下這些方面的知識。
第一步:安裝環境
需要安裝的有:
- nodejs,並添加入環境變量PATH
- 使用nodejs安裝vue-cli
參考內容:
http://cn.vuejs.org/guide/installation.html#u547D_u4EE4_u884C_u5DE5_u5177
使用命令:
npm install -g vue-cli - 使用nodejs安裝webpack和webpack-dev-server
參考內容:
http://webpack.github.io/docs/tutorials/getting-started/
使用命令:
npm install webpack -g
之所以要在全局安裝webpack是因為使用webpack的命令行方便,不需要在每一個項目中到node_module中調用。 - Atom編輯器
這個從網上下載,https://atom.io/。這是一個開源的編輯器軟件,之所以選擇atom,是因為它集合了sublimeText和其他一些編輯器的優點。最大的好處是可以使用package插件的形式對atom編輯器進行自定義擴展。
第二步:創建項目模板
vue init wepack vue-multipage-demo
如上所示,這條命令的意思是使用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 使用Git版本管理時需要忽略的目錄,用於git設置
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" }
其中包括了由項目自動生成的一些插件。
我梳理一下,主要有下面這些,其中標注紅色的是我自己用來開發依賴的:
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; }
因為我們的想法是要將所有的業務模塊放在module中,這樣一來的話,就在module中細分,最后輸出html都在dist的module下。這里的字符串操作也是和路徑的情況相匹配的,如果有需要進行其他方式的設定,注意在這里修改路徑的識別。
webpack.dev.conf.js
在打開后,我們會發現在這里有一個插件的設置,如圖10:
圖10
這個 插件就是剛才提到的將輸出html頁面build結果的地方。
首先,添加
var path = require('path'); var glob = require('glob');
用來引入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; }
然后再添加這一段,
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)); }
這個同樣是通過指定的路徑,按照我之前的預想,進行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的源代碼進行構建變成瀏覽器能夠識別的正常文件。這樣就大大降低了前端開發的重復性。
/2016-09-13 補 /
這個是我的一個demo,提供給學生用的。
http://www.huyangsheng.cn/resource/vue-multipage-demo.rar
以上文章是參考了幾篇之后弄出來一個適合自己用的。
參考:
https://github.com/Coffcer/Blog/issues/1
http://cnu4.github.io/2016/03/21/Webpack-Vue-MultiplePage/
http://jiongks.name/blog/just-vue/?from=groupmessage&isappinstalled=1
http://www.cnblogs.com/grimm/p/5768433.html
https://github.com/yaoyao1987/vue-cli-multipage
---------------------轉發結束--------------------