手把手帶你把vue+webpack 單頁面改多頁面(適合上手),支持多級目錄

前言

公司作的後臺管理系統,越作越龐大,並且系統之間還須要常常的來回嵌套頁面,單頁面已經不太順手了。
因此我把vue+elementui+webpack單頁面改成多頁面的經驗在這裏嘮叨嘮叨,這裏做展現的是一個簡單的後臺管理系統,利用iframe模擬的路由跳轉,很簡單也很容易上手,能夠把這個項目下載到本地,而後把大家的頁面慢慢移進去,但願能幫到一些小夥伴。

建議,把項目下載下來跑起來,結合着項目看這篇文章,否則會蒙。
gitHub:歡迎各位star
在線預覽:網站不太穩定,最好下載到本地
效果預覽:
圖片描述css

思路

一.廣泛的實現方案:html

1.手動改造webpack,配置多個入口,配置多個出口;
2.每一個目錄下邊都有個.html文件來承載實例,.js文件引入Vue等等模塊,.vue頁面來書寫邏輯等,如圖:
clipboard.png

二.改進的方案vue

1.用node自帶的模塊fs來動態的匹配目錄,動態的生成入口文件,動態的生成打包出口文件;
2.咱們寫一個公共的html文件來承載實例,寫一個公共的js來引入各類依賴,根據動態傳入.vue文件模塊生成實例
如圖:

clipboard.png

3.解釋一下template下的config.js:
由於咱們如今只用config.js來去引入各類依賴,就像單頁面的mian.js同樣,不一樣的是,
須要被掛載的vue文件是動態的,因此咱們用localStorage來傳遞,咱們在頁面目錄下邊只用寫一個.vue文件,一個.js文件,
這個.js文件裏只用寫上當前對應的.vue文件所在的目錄,不用在每一個js裏寫那麼多引入的依賴

文件目錄下的js:node

let baseUrl = "china/china"
localStorage.setItem('baseUrl', baseUrl)

template/config.jswebpack

// 若是你想用本身建立的實例,在本身單獨的js文件里加上:let baseUrl="noNeed" / localStorage.setItem('baseUrl',baseUrl)
let baseMounted = localStorage.getItem('baseUrl')
console.log(baseMounted)

import '../src/style/index.scss' //公用樣式

if (baseMounted === 'noNeed') {
  // 組件本身建立了實,將不會再引入下邊的資源
  throw new Error("當前組件本身建立了實例,不會引用公用方法、實例");
}
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
// 動態捕獲要掛載實例的.vue文件的路徑
var App = resolve => require.ensure([], () => resolve(require("../src/views/" + baseMounted + ".vue")));
new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
})

總結:就是你每次切換頁面的時候,會先加載本身目錄下的js文件,js裏用localStorage存儲.vue的路徑(固然你也能夠寫成'noNeed',這樣你本身就得在js裏去引入各類依賴了),
再去引用template/config.js的時候,利用localStorage告訴掛載實例的模板是哪一個。git

三.最重要的webpack配置github

webpack的複雜程度我就不累贅了(我本身也是個入門選手),這個須要本身花時間去看,我就直接講下實現的結果。
主要的實現邏輯就是下邊的這個js文件,出處我翻不到了,不知道是哪位大神研究出來的,
這個js文件主要實現了webpack匹配出入口文件的功能,
一開始,我也是研究了研究裏邊的方法,而後在原版的基礎上改造了好幾版,實現瞭如今的效果,
主要改了公共模板html和js,以及js的加載順序。

build下的這三個文件都要改爲multipage-helper.js裏的方法web

clipboard.png

multipage-helper.js:element-ui

var path = require('path')
var fs = require("fs")
const resolve = (p) => path.resolve(__dirname, "..", p)
var HtmlWebpackPlugin = require('html-webpack-plugin')
const templatePath = resolve("template/index.html")
const templateJs = "./template/config.js"

var moduleList //緩存多頁面模塊列表
var moduleRootPath = './src/views' //模塊根目錄(這個能夠根據本身的需求命名)

/**
 * 獲取js入口數組
 */
exports.getEntries = function getEntries() {
  //緩存js入口數組
  var entries = {}
  //初始化模塊列表
  this.getModuleList()
  //變量模塊列表
  moduleList.forEach(function(module) {
    if (module.moduleID != "" && module.moduleJS != "") {
      entries[module.moduleID] = module.moduleJS
    }
  })
  entries.app=templateJs
  console.log("*********************************** entries ***********************************")
  console.log(entries)
  return entries
}

/**
 * 獲取多頁面模塊列表
 * @returns {模塊的信息集合}
 */
exports.getModuleList = function getModuleList() {
  //判斷是否爲空,不爲空則直接返回
  if (moduleList) {
    return moduleList
  } else { //爲空則讀取列表
    moduleList = new Array();
    readDirSync(moduleRootPath, "")
    console.log("*********************************** moduleList ***********************************")
    console.log(moduleList)
    return moduleList
  }
}

/**
 * 獲取dev的Html模板集合
 * @returns {dev的Html模板集合}
 */
exports.getDevHtmlWebpackPluginList = function getDevHtmlWebpackPluginList() {
  console.log("*********************************** devHtmlWebpackPluginList ***********************************")
  //緩存dev的Html模板集合
  var devHtmlWebpackPluginList = []
  //獲取多頁面模塊集合
  var moduleList = this.getModuleList()
  //遍歷生成模塊的HTML模板
  moduleList.forEach(function(mod) {
    //生成配置
    var conf = {
      filename: mod.moduleID + ".html",
      template: mod.moduleHTML ? mod.moduleHTML : templatePath,
      chunks: [mod.moduleID,'app'],
      chunksSortMode: 'manual',
      inject: true
    }
    console.log(conf)
    //添加HtmlWebpackPlugin對象
    devHtmlWebpackPluginList.push(new HtmlWebpackPlugin(conf))
  })
  return devHtmlWebpackPluginList
}

/**
 * 獲取prod的Html模板集合
 * @returns {prod的Html模板集合}
 */
exports.getProdHtmlWebpackPluginList = function getProdHtmlWebpackPluginList() {
  console.log("*********************************** prodHtmlWebpackPluginList ***********************************")
  //緩存dev的Html模板集合
  var prodHtmlWebpackPluginList = []
  //獲取多頁面模塊集合
  var moduleList = this.getModuleList()
  //遍歷生成模塊的HTML模板
  moduleList.forEach(function(mod) {
    //生成配置
    var conf = {
      filename: mod.moduleID + ".html",
      template: mod.moduleHTML ? mod.moduleHTML : templatePath,
      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', mod.moduleID,'app'],
      chunksSortMode: 'manual'
    }
    console.log(conf)
    //添加HtmlWebpackPlugin對象
    prodHtmlWebpackPluginList.push(new HtmlWebpackPlugin(conf))
  })
  return prodHtmlWebpackPluginList
}

/**
 * 深度遍歷目錄,並整理多頁面模塊
 * @param path 須要變量的路徑
 * @param moduleName 模塊名稱
 */
function readDirSync(path, moduleName) {
  //緩存模塊對象
  var module = { moduleID: "", moduleHTML: "", moduleJS: "" }
  //獲取當前模塊ID
  var moduleID = path.replace(moduleRootPath + "/", "")
  if (path == moduleRootPath) {
    moduleID = ""
  }
  module.moduleID = moduleID
  //獲取目錄下全部文件及文件夾
  var pa = fs.readdirSync(path)
  pa.forEach(function(ele, index) {
    var info = fs.statSync(path + "/" + ele)
    if (info.isDirectory()) {
      // console.log("dir: "+ele)
      readDirSync(path + "/" + ele, ele)
    } else {
      //判斷當前模塊的html是否存在
      if (moduleName+".html" == ele){
        module.moduleHTML = path+"/"+ele
      }
      // module.moduleHTML = templatePath

      //判斷當前模塊的js是否存在
      if (moduleName + ".js" == ele) {
        module.moduleJS = path + "/" + ele
      }
      // console.log("file: "+ele)
    }
  })
  //判斷模塊是否真實(可能只是個分級目錄)
  if ((module.moduleID != "" && module.moduleHTML != "") || (module.moduleID != "" && module.moduleJS != "")) {
    moduleList.push(module)
  }
}

鄙人的webpack正在學習中,因此可能有些細節講的不會太清楚,但能用,但願你們的指正,也但願能幫到你們,嘻嘻嘻。數組

相關文章
相關標籤/搜索