Vue CLI3基礎(chǔ)學(xué)習(xí)之pages構(gòu)建多頁應(yīng)用
前言
首先我們可以把多頁應(yīng)用理解為由多個單頁構(gòu)成的應(yīng)用,而何謂多個單頁呢?其實你可以把一個單頁看成是一個 html 文件,那么多個單頁便是多個 html 文件,多頁應(yīng)用便是由多個 html 組成的應(yīng)用,如下圖所示
既然多頁應(yīng)用擁有多個 html ,那么同樣其應(yīng)該擁有多個獨立的入口文件、組件、路由、 vuex 等。沒錯,說簡單一點就是多頁應(yīng)用的每個單頁都可以擁有單頁應(yīng)用 src 目錄下的文件及功能,我們來看一下一個基礎(chǔ)多頁應(yīng)用的目錄結(jié)構(gòu)
├── node_modules # 項目依賴包目錄
├── build # 項目 webpack 功能目錄
├── config # 項目配置項文件夾
├── src # 前端資源目錄
│ ├── images # 圖片目錄
│ ├── components # 公共組件目錄
│ ├── pages # 頁面目錄
│ │ ├── page1 # page1 目錄
│ │ │ ├── components # page1 組件目錄
│ │ │ ├── router # page1 路由目錄
│ │ │ ├── views # page1 頁面目錄
│ │ │ ├── page1.html # page1 html 模板
│ │ │ ├── page1.vue # page1 vue 配置文件
│ │ │ └── page1.js # page1 入口文件
│ │ ├── page2 # page2 目錄
│ │ └── index # index 目錄
│ ├── common # 公共方法目錄
│ └── store # 狀態(tài)管理 store 目錄
├── .gitignore # git 忽略文件
├── .env # 全局環(huán)境配置文件
├── .env.dev # 開發(fā)環(huán)境配置文件
├── .postcssrc.js # postcss 配置文件
├── babel.config.js # babel 配置文件
├── package.json # 包管理文件
├── vue.config.js # CLI 配置文件
└── yarn.lock # yarn 依賴信息文件
二、多入口
在單頁應(yīng)用中,我們的入口文件只有一個, CLI 默認(rèn)配置的是 main.js ,但是到了多頁應(yīng)用,我們的入口文件便包含了 page1.js 、 page2.js 、 index.js 等,數(shù)量取決于 pages 文件夾下目錄的個數(shù),這時候為了項目的可拓展性,我們需要自動計算入口文件的數(shù)量并解析路徑配置到 webpack 中的 entry 屬性上,如:
module.exports = { ... entry: { page1: '/xxx/pages/page1/page1.js', page2: '/xxx/pages/page2/page2.js', index: '/xxx/pages/index/index.js', }, ... }
那么我們?nèi)绾巫x取并解析這樣的路徑呢,這里就需要使用工具和函數(shù)來解決了。我們可以在根目錄新建 build 文件夾存放 utils.js 這樣共用的 webpack 功能性文件,并加入多入口讀取解析方法
/* utils.js */ const path = require('path'); // glob 是 webpack 安裝時依賴的一個第三方模塊,該模塊允許你使用 * 等符號, // 例如 lib/*.js 就是獲取 lib 文件夾下的所有 js 后綴名的文件 const glob = require('glob'); // 取得相應(yīng)的頁面路徑,因為之前的配置,所以是 src 文件夾下的 pages 文件夾 const PAGE_PATH = path.resolve(__dirname, '../src/pages'); /* * 多入口配置 * 通過 glob 模塊讀取 pages 文件夾下的所有對應(yīng)文件夾下的 js * 后綴文件,如果該文件存在 * 那么就作為入口處理 */ exports.getEntries = () => { let entryFiles = glob.sync(PAGE_PATH + '/*/*.js') // 同步讀取所有入口文件 let map = {} // 遍歷所有入口文件 entryFiles.forEach(filePath => { // 獲取文件名 let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.')) // 以鍵值對的形式存儲 map[filename] = filePath }) return map }
讀取并存儲完畢后,我們得到了一個入口文件的對象集合,這個對象我們便可以將其設(shè)置到 webpack 的 entry 屬性上,這里我們需要修改 vue.config.js 的配置來間接修改 webpack 的值
/* vue.config.js */ const utils = require('./build/utils') module.exports = { ... configureWebpack: config => { config.entry = utils.getEntries() }, ... }
這樣我們多入口的設(shè)置便完成了,當(dāng)然這并不是 CLI 所希望的操作,后面我們會進行改進。
三、多模板
相對于多入口來說,多模板的配置也是大同小異,這里所說的模板便是每個 page 下的 html 模板文件,而模板文件的作用主要用于 webpack 中 html-webpack-plugin 插件的配置,其會根據(jù)模板文件生產(chǎn)一個編譯后的 html 文件并自動加入攜帶 hash 的腳本和樣式,基本配置如下
/* webpack 配置文件 */ const HtmlWebpackPlugin = require('html-webpack-plugin') // 安裝并引用插件 module.exports = { ... plugins: [ new HtmlWebpackPlugin({ title: 'My Page', // 生成 html 中的 title filename: 'demo.html', // 生成 html 的文件名 template: 'xxx/xxx/demo.html', // 模板路徑 chunks: ['manifest', 'vendor', 'demo'], // 所要包含的模塊 inject: true, // 是否注入資源 }) ] ... }
以上是單模板的配置,那么如果是多模板只要繼續(xù)往 plugins 數(shù)組中添加 HtmlWebpackPlugin 即可,但是為了和多入口一樣能夠靈活的獲取 pages 目錄下所有模板文件并進行配置,我們可以在 utils.js 中添加多模板的讀取解析方法
/* utils.js */ // 多頁面輸出配置 // 與上面的多頁面入口配置相同,讀取 page 文件夾下的對應(yīng)的 html 后綴文件,然后放入數(shù)組中 exports.htmlPlugin = configs => { 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', // 生成 html 的文件名 chunks: ['manifest', 'vendor', filename], inject: true, } // 如果有自定義配置可以進行 merge if (configs) { conf = merge(conf, configs) } // 針對生產(chǎn)環(huán)境配置 if (process.env.NODE_ENV === 'production') { conf = merge(conf, { minify: { removeComments: true, // 刪除 html 中的注釋代碼 collapseWhitespace: true, // 刪除 html 中的空白符 // removeAttributeQuotes: true // 刪除 html 元素中屬性的引號 }, chunksSortMode: 'manual' // 按 manual 的順序引入 }) } arr.push(new HtmlWebpackPlugin(conf)) }) return arr }
- 以上我們?nèi)匀皇鞘褂?glob 讀取所有模板文件,然后將其遍歷并設(shè)置每個模板的 config ,同時針對一些自定義配置和生產(chǎn)環(huán)境的配置進行了 merge 處理,其中自定義配置的功能我會在下節(jié)進行介紹,這里介紹一下生產(chǎn)環(huán)境下 minify 配置的作用:將 html-minifier 的選項作為對象來縮小輸出。
- html-minifier 是一款用于縮小 html 文件大小的工具,其有很多配置項功能,包括上述所列舉的常用的刪除注釋、空白、引號等。
- 當(dāng)我們編寫完了多模板的方法后,我們同樣可以在 vue.config.js 中進行配置,與多入口不同的是我們在 configureWebpack 中不能直接替換 plugins 的值,因為它還包含了其他插件
/* vue.config.js */ const utils = require('./build/utils') module.exports = { ... configureWebpack: config => { config.entry = utils.getEntries() // 直接覆蓋 entry 配置 // 使用 return 一個對象會通過 webpack-merge 進行合并,plugins 不會置空 return { plugins: [...utils.htmlPlugin()] } }, ... }
如此我們多頁應(yīng)用的多入口和多模板的配置就完成了,這時候我們運行命令 yarn build 后你會發(fā)現(xiàn) dist 目錄下生成了 3 個 html 文件,分別是 index.html 、 page1.html 和 page2.html
四、使用 pages 配置
其實,在 vue.config.js 中,我們還有一個配置沒有使用,便是 pages 。 pages 對象允許我們?yōu)閼?yīng)用配置多個入口及模板,這就為我們的多頁應(yīng)用提供了開放的配置入口。官方示例代碼如下
/* vue.config.js */ module.exports = { pages: { index: { // page 的入口 entry: 'src/index/main.js', // 模板來源 template: 'public/index.html', // 在 dist/index.html 的輸出 filename: 'index.html', // 當(dāng)使用 title 選項時, // template 中的 title 標(biāo)簽需要是 <title><%= htmlWebpackPlugin.options.title %></title> title: 'Index Page', // 在這個頁面中包含的塊,默認(rèn)情況下會包含 // 提取出來的通用 chunk 和 vendor chunk。 chunks: ['chunk-vendors', 'chunk-common', 'index'] }, // 當(dāng)使用只有入口的字符串格式時, // 模板會被推導(dǎo)為 `public/subpage.html` // 并且如果找不到的話,就回退到 `public/index.html`。 // 輸出文件名會被推導(dǎo)為 `subpage.html`。 subpage: 'src/subpage/main.js' } }
我們不難發(fā)現(xiàn), pages 對象中的 key 就是入口的別名,而其 value 對象其實是入口 entry 和模板屬性的合并,這樣我們上述介紹的獲取多入口和多模板的方法就可以合并成一個函數(shù)來進行多頁的處理,合并后的 setPages 方法如下
// pages 多入口配置 exports.setPages = configs => { let entryFiles = glob.sync(PAGE_PATH + '/*/*.js') let map = {} entryFiles.forEach(filePath => { let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.')) let tmp = filePath.substring(0, filePath.lastIndexOf('\/')) let conf = { // page 的入口 entry: filePath, // 模板來源 template: tmp + '.html', // 在 dist/index.html 的輸出 filename: filename + '.html', // 頁面模板需要加對應(yīng)的js腳本,如果不加這行則每個頁面都會引入所有的js腳本 chunks: ['manifest', 'vendor', filename], inject: true, }; if (configs) { conf = merge(conf, configs) } if (process.env.NODE_ENV === 'production') { conf = merge(conf, { minify: { removeComments: true, // 刪除 html 中的注釋代碼 collapseWhitespace: true, // 刪除 html 中的空白符 // removeAttributeQuotes: true // 刪除 html 元素中屬性的引號 }, chunksSortMode: 'manual'// 按 manual 的順序引入 }) } map[filename] = conf }) return map }
上述代碼我們 return 出的 map 對象就是 pages 所需要的配置項結(jié)構(gòu),我們只需在 vue.config.js 中引用即可
/* vue.config.js */ const utils = require('./build/utils') module.exports = { ... pages: utils.setPages(), ... }
這樣我們多頁應(yīng)用基于 pages 配置的改進就大功告成了,當(dāng)你運行打包命令來查看輸出結(jié)果的時候,你會發(fā)現(xiàn)和之前的方式相比并沒有什么變化,這就說明這兩種方式都適用于多頁的構(gòu)建,但是這里還是推薦大家使用更便捷的 pages 配置
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。
相關(guān)文章
關(guān)于element?ui?表格中的常見特殊屬性說明
這篇文章主要介紹了關(guān)于element?ui?表格中的常見特殊屬性說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08Vue中搭配Bootstrap實現(xiàn)Vue的列表增刪功能
日常開發(fā)中,我們可以用?“拿來主義”?借助Bootstarp現(xiàn)成的一些樣式,快速生成我們想要的頁面布局,避免書寫大量的HTML和CSS代碼,省下了許多不必要的時間,可以直接搭配vue使用2022-11-11Vue3 響應(yīng)式數(shù)據(jù) reactive使用方法
這篇文章主要介紹了Vue3 響應(yīng)式數(shù)據(jù) reactive使用方法,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-11-11解決vue組件銷毀之后計時器繼續(xù)執(zhí)行的問題
這篇文章主要介紹了解決vue組件銷毀之后計時器繼續(xù)執(zhí)行的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07