能夠根據不一樣的環境生成指定的路由文件,而不是一次性打包全部文件,默承認以遍歷page目錄下的全部.vue文件。html
--test
InitRouterPlugin.js
,使用yargs
模塊獲取命令行參數const argv = require('yargs').argv
console.log(argv.test)
複製代碼
生成路由文件應在全部事情開始以前執行,webpack提供的生命週期鉤子實在太多,這裏就挑了一個最靠前的afterPlugins
,有興趣的能夠看下這張完整的生命週期圖。vue
webpack plugin對外暴露的apply
函數,經過apply函數獲取主引擎compiler
webpack
module.exports = class InitRouterPlugin {
constructor(options) {
this.options = options
}
apply(compiler) {
compiler.hooks.afterPlugins.tap('InitRouterPlugin', async (context, entry) => {
await writeRouter()
})
}
}
複製代碼
這裏奇怪的換行是爲了生成後的文件保持格式規範web
let route = `import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
const array = [
`
複製代碼
這裏使用的是路由懶加載模式vue-router
const fs = require('fs').promises
const path = require('path')
async function getPage(filePath) {
let files = await fs.readdir(filePath)
for (const filename of files) {
const filedir = path.join(filePath, filename)
const filehandle = await fs.open(filedir)
const stat = await filehandle.stat()
await filehandle.close()
const isFile = stat.isFile()
const isDir = stat.isDirectory()
if (isFile) {
route += ` { path: 'filename.split(".")[0]}', component: () => import('@/page${filedir.split("page")[1].replace(/\\/g, "/")}') },
`
}
if (isDir) {
await getPage(filedir) //遞歸,若是是文件夾,就繼續遍歷該文件夾下面的文件
}
}
}
複製代碼
fs模塊的promise語法寫起來舒服多了。json
async function writeRouter() {
if (argv.test) {
// 自定義邏輯
} else {
await getPage(path.resolve('path/to/page'))
route = route.slice(0, -2) // 去掉最後一個換行和逗號
}
route += `
]
export default new Router({
routes: array
})
`
const routeFile = await fs.open(path.resolve('path/to/router.js'), 'w')
await routeFile.writeFile(route)
await routeFile.close()
}
複製代碼
webpack內容實在太多,文檔寫的也不是很清楚,有些鉤子的說明甚至只有一個名字,是讓咱們本身去摸索嗎(╯°Д°)╯︵ ┻━┻,實在是太南了。目前新增vue文件的話須要從新編譯纔會生成新的路由文件。原本還想試試監聽文件的改動實時更新router.js文件,可是沒有找到合適的方法。若是隻是文件內容的改動,而不是新增vue就觸發的話,就過於頻繁了,我認爲沒有必要。歡迎在評論區提出意見~promise