vue-cli3.0 多頁面配置

看這個吧Vue cli3 通用多頁面腳手架

前言

vue-cli是Vue.js官方推出的腳手架,它功能豐富、擴展性強,爲Vue應用開發帶來了極大的便捷,它提供了多種開發範式,詮釋了開箱即用。vue-cli@3版本經歷了alpha、beta、rc版本近7個月的迭代開發,在最近幾天正式版終於發佈,本文主要講解如何使用vue-cli建立一個多入口工程,若要近一步瞭解vue-cli,請訪問官方文檔css

什麼是多頁應用

單頁應用(SPA)每每只含有包含一個主入口文件與index.html,頁面間切換經過局部刷新資源來完成。而在多頁應用中,咱們會爲每一個HTML文檔文件都指定好一個JS入口,這樣一來當頁面跳轉時用戶會得到一個新的HTML文檔,整個頁面會從新加載。html

單頁應用、多頁應用的優劣勢在此就不進行分析了,總而言之,多頁架構模式暫時是沒法取代的,若是嘗試把幾十個不關聯的頁面作成一個,那麼開發成本會很是大的,Not every app has to be an SPAvue

初始化項目

首先咱們安裝好vue-cli腳手架,並初始化一個默認工程. 修改項目目錄:webpack

.
├── assets
│   └── logo.png
├── components
│   ├── About.vue
│   ├── HelloWorld.vue
│   └── Home.vue
├── pages
│   ├── page1
│   │   ├── page1.html
│   │   ├── page1.js
│   │   └── page1.vue
│   └── page2
│       ├── page2.html
│       ├── page2.js
│       └── page2.vue
└── style
    ├── common.css
    └── common.less

複製代碼

vue.config.js是一個可選文件,用戶須要自行建立,它會被@vue/cli-service讀取。當正確添加配置後,重啓一下項目,測試一下項目在改變目錄結構後可否正常運行。試想一下,若照着這個思路進行配置多入口,那麼首先須要刪除或修改掉原有webpack配置項,而後還需添加多入口的一些插件,雖然經過腳手架對外提供的API能夠實現,但是這種修改方式還不是直接修改原生構建配置更快,那麼還有其餘解決方法嗎?web

vue.config.js 配置

let path = require('path')
let glob = require('glob')
//配置pages多頁面獲取當前文件夾下的html和js
function getEntry(globPath) {
	let entries = {},
		basename, tmp, pathname, appname;

	glob.sync(globPath).forEach(function(entry) {
		basename = path.basename(entry, path.extname(entry));
		// console.log(entry)
		tmp = entry.split('/').splice(-3);
		console.log(tmp)
		pathname = basename; // 正確輸出js和html的路徑

		// console.log(pathname)
		entries[pathname] = {
			entry: 'src/' + tmp[0] + '/' + tmp[1] + '/' + tmp[1] + '.js',
			template: 'src/' + tmp[0] + '/' + tmp[1] + '/' + tmp[2],
			title:  tmp[2],
			filename: tmp[2]
		};
	});
	return entries;
}

let pages = getEntry('./src/pages/**?/*.html');
console.log(pages)
//配置end

module.exports = {
	lintOnSave: false, //禁用eslint
	baseUrl:process.env.NODE_ENV === "production"?'https://www.mycdn.com/':'/',
	productionSourceMap: false,
	pages,
	devServer: {
		index: 'page1.html', //默認啓動serve 打開page1頁面
		open: process.platform === 'darwin',
		host: '',
		port: 8088,
		https: false,
		hotOnly: false,
		proxy: {
			'/xrf/': {
				target: 'http://reg.tool.hexun.com/',
				changeOrigin: true,
				pathRewrite: {
					'^/xrf': ''
				}
			},
			'/wa/': {
				target: 'http://api.match.hexun.com/',
				changeOrigin: true,
				pathRewrite: {
					'^/wa': ''
				}
			}
		}, // 設置代理
		before: app => {}
	},
	chainWebpack: config => {
		config.module
			.rule('images')
			.use('url-loader')
			.loader('url-loader')
			.tap(options => {
				// 修改它的選項...
				options.limit = 100
				return options
			})
		Object.keys(pages).forEach(entryName => {
			config.plugins.delete(`prefetch-${entryName}`);
		});
		if(process.env.NODE_ENV === "production") {
			config.plugin("extract-css").tap(() => [{
				path: path.join(__dirname, "./dist"),
				filename: "css/[name].[contenthash:8].css"
			}]);
		}
	},
	configureWebpack: config => {
		if(process.env.NODE_ENV === "production") {
			config.output = {
				path: path.join(__dirname, "./dist"),
				filename: "js/[name].[contenthash:8].js"			
			};
		}
	}
}
複製代碼

dist打包目錄

├── css
│   ├── page1.9951d5a1.css
│   └── page2.009d0d6f.css
├── img
│   └── logo.82b9c7a5.png
├── js
│   ├── chunk-vendors.f061f10e.js
│   ├── page1.5a5322e0.js
│   └── page2.db57562b.js
├── page1.html
└── page2.html


複製代碼

源碼部分

@vue/cli-service經過判斷是否傳入pages參數來生成對應Webpack配置文件,讓咱們先來看看沒有傳入時的處理函數:vue-cli

if (!multiPageConfig) {
      // default, single page setup.
      htmlOptions.template = fs.existsSync(htmlPath)
        ? htmlPath
        : defaultHtmlPath

      webpackConfig
        .plugin('html')
          .use(HTMLPlugin, [htmlOptions])

      if (!isLegacyBundle) {
        // inject preload/prefetch to HTML
        ...
      }
    }
複製代碼

由源碼可知,pages參數可用於生成三個插件:preload-plugin、prefetch-plugin、html-plugin,若不傳html文件則會使用一個只空的默認html文件,而在多入口模式下,代碼的邏輯也很簡單,在此就不貼源碼了,它會執行如下步驟:api

  1. 清除原有entry
  2. 對pages字段的每一個key作循環,解析每一個入口對象的參數entry(必填)、title、template、filename、chunks
  3. 經過entry字段生成webpack的entry入口
  4. 經過其他參數生成對應的html-webpack-plugin,若不爲傳統模式,也會生成對應入口的preload插件與prefetch插件

局部優化

移除prefetch

因爲本人並不喜歡爲未來作打算,所以並不但願預加載一些可能會用到的asyncChunk,由於會浪費掉一些帶寬,並且在多頁面中並不見得預加載其餘入口的文件是一件好事情,因而咱們經過chainWebpack進行刪除:瀏覽器

modules.exports = {
	// ...
  chainWebpack: config => {
    Object.keys(pages).forEach(entryName => {
      config.plugins.delete(`prefetch-${entryName}`);
    });
  }
}
複製代碼

關閉SourceMap

關閉以後不只能加快生產環境的打包速度,也能避免源碼暴露在瀏覽器端:bash

modules.exports = {
	// ...
    productionSourceMap: false,
}
複製代碼

打包分類(強迫症患者福音)

首先回顧一下dist中的部分文件夾:架構

dist打包目錄

├── css
│   ├── page1.9951d5a1.css
│   └── page2.009d0d6f.css
├── img
│   └── logo.82b9c7a5.png
├── js
│   ├── chunk-vendors.f061f10e.js
│   ├── page1.5a5322e0.js
│   └── page2.db57562b.js
├── page1.html
└── page2.html


複製代碼
相關文章
相關標籤/搜索