SPA單頁面應用:指的是隻有一個主頁面的應用(只有一個html頁面),專案啟動時載入主頁面時會一次性載入所有的js、css等相關資源(需要進行首屏優化)。所有內容都包含在主頁面中,對每一個功能模組元件化。單頁面的跳轉實質上就是切換相關元件,僅僅重新整理區域性資源。
MPA多頁面應用:指的是有多個獨立的頁面(多個HTML頁面),開啟不同的頁面時會載入相關的js以及css資源,公共資源會重複載入。多頁面應用跳轉,需要整個頁面進行重新整理。
1、重新整理方式
2、路由模式
3、使用者體驗
4、資料傳遞
5、使用範圍
1、使用vue init webpack "專案名"
2、完成後,使用cd "專案檔名"
及 npm isntall
安裝依賴,最後使用npm run dev
啟動專案。
有了上面的概念以及專案基礎搭建,我們可以在vue-cli腳手架搭建的SPA專案上做一些修改,使其變成MPA應用。
首先,可以建立一下下面紅色方框的目錄結構,需要注意的是我們需要把mian.js檔案改名為index.js,保證頁面入口js檔案和模板檔名保持一致,上面紅色方框的檔案是webpack初始化的檔案。
1、在build/utils.js中我們新增兩個方法,分別為多入口檔案和多頁面輸出。
const path = require('path')
const glob = require('glob')
const PAGE_PATH = path.resolve(__dirname, '../src/pages');
const HtmlWebpackPlugin = require('html-webpack-plugin'); //對每個頁面單獨打包生成一個新頁面的外掛
const merge = require('webpack-merge')
// 多入口設定
exports.entries = function() {
var entryFiles = glob.sync(PAGE_PATH + '/*/*.js')
var map = {}
entryFiles.forEach((filePath) => {
// /index.js
var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.')) // index
map[filename] = filePath; // map[index] = PAGE_PATH + /index/index.js
})
return map;
}
// 多頁面輸出設定
exports.htmlPlugin = function() {
let entryHtml = glob.sync(PAGE_PATH + '/*/*.html')
let arr = []
entryHtml.forEach((filePath) => {
let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
let conf = {
template: filePath,
filename: filename + '.html',
chunks: [filename],
inject: true
}
if(process.env.NODE_ENV === 'production') {
conf = merge(conf, {
chunks: ['manifest', 'vendor', filename],
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
})
}
arr.push(new HtmlWebpackPlugin(conf))
})
return arr
}
2、修改build/webpack.base.conf.js的入口設定。
entry: {
app: './src/main.js',
}
更換為
entry: utils.entries(),
3、修改build/webpack.dev.conf.js和build/webpack.prod.conf.js的多頁面設定:把原有的頁面模板設定註釋或刪除,並把多頁面設定新增到plugins。
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { 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',
// chunks: ['manifest', 'vendor', 'app'],
// }),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// 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',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
].concat(utils.htmlPlugin()) // 重點
文章參考資料:
Vue單頁面與多頁面的區別
碼雲地址