webpack 搭建vue多單頁應用

爲什麼選擇多單頁

最近在覈心業務上作了一項新的嘗試,拋棄臃腫的PHP後端渲染的多頁應用模式,全站改造單頁應用。單頁渲染在加載速度已經有了極大的提高,而且MVVM的模式使前端開發從繁瑣的DOM操做中解放出來。爲何考慮多單頁模式,可綜合多頁和單頁的優點,多頁分離減小模塊耦合,特別是應用複雜程度高時,此後也可在每一個單頁裏面嘗試不一樣的方案,利於拓展。本文是記錄多單頁實踐的思路,腳手架vue-cli生成,詳細的代碼可參考demo,歡迎探討。css

webpck搭建多單頁

1.從入口文件entry提及

entry對象主要用於配置應用js入口文件,由模塊名稱爲屬性名(編譯生成的js chunks的名稱),以該js文件路徑爲屬性值。以vue-cli搭建的單頁應用爲例,如下是初始配置。單頁應用一般只有一個入口js文件(不包括其餘公共js模塊)。html

多單頁應用則有多個js入口文件,entry也要配置多個入口,以下: webpack.base.conf.js前端

entry: {
    'index': './src/pages/main.js',// index.html 的入口文件
    'asset': './src/pages/asset/index.js',// 頁面 asset.html 的入口文件
    'login': './src/pages/login/index.js',// 頁面 login.html 的入口文件
  },
複製代碼

當頁面應用比較多的時候,能夠引入glob模塊,封裝遍歷函數。vue

//引入模塊
var glob = require('glob');

//遍歷函數
function getEntry(globPath) {
  var entries = {},
    basename, tmp, pathname;
    //下面的路徑根據本身的目錄結構修改,打印出來檢查是否跟手寫的一致
  glob.sync(globPath).forEach(function (entry) {
    basename = path.basename(entry, path.extname(entry));
    console.log("basename",basename);
    tmp = entry.split('/').splice(-3);
    pathname = tmp.splice(0, 1) + '/' + tmp.splice(0, 1) + '/' + basename; // 正確輸出js和html的路徑
    entries[pathname] = entry;
  });
  return entries;
}

//遍歷pages路徑下全部的main.js文件,全部的入口文件命名一致
var entries=getEntry('./src/pages/**/main.js');

// 傳值
 entry: entries,
複製代碼

關於entry更詳細的內容可參考官網webpack

2. 多頁應用還需修改HtmlWebpackPlugin配置頁面渲染模版

webpack.dev.conf.jsgit

new HtmlWebpackPlugin(
    {
    //訪問
      filename: 'pages/login/login.html',
      template: './src/pages/login/login.html',
      inject: true,
    //對應entry的chunks名稱
      chunks:['login']
    }),
    new HtmlWebpackPlugin({
      filename: 'pages/asset/asset.html',
      template: './src/pages/asset/asset.html',
      inject: true,
      chunks:['asset']
    }),
複製代碼

寫成遍歷: webpack.dev.conf.jses6

var pages = getEntry('./src/pages/**/*.html');
for (var pathname in pages) {
  // 配置生成的html文件,定義路徑等
  var conf = {
    filename: pathname + '.html',
    template: pages[pathname],   // 模板路徑
    inject: true              // js插入html尾部
  };
   if (pathname in baseWebpackConfig.entry) {
   //這裏配置當前單頁須要加載的chunks
    conf.chunks = ['manifest', 'vendor',pathname];
    conf.hash = true;
   }
  devWebpackConfig.plugins.push(new HtmlWebpackPlugin(conf));
}

//遍歷函數
function getEntry(globPath) {
  var entries = {}, basename, tmp, pathname;

  glob.sync(globPath).forEach(function (entry) {
    basename = path.basename(entry, path.extname(entry));
    tmp = entry.split('/').splice(-3);
    pathname = tmp.splice(0, 1) + '/' + tmp.splice(0, 1) + '/' + basename; // 正確輸出js和html的路徑
    entries[pathname] = entry;
  });
  return entries;
}

複製代碼

webpack構建多單頁一些踩過的坑

  1. webpack打包後樣式丟失 檢查了很久發現是這2個插件衝突的問題,postCss loader 與 OptimizeCSSPlugin。 解決:去掉下列代碼。
new OptimizeCSSPlugin({
      cssProcessorOptions: config.build.productionSourceMap
        ? { safe: true, map: { inline: false } }
        : { safe: true }
    }),
複製代碼
  1. cannot find the element #app 單頁頁面加載了其餘頁面的入口文件,找不到對應的模版id致使。解決:在webpack配置,在前面HtmlWebpackPlugin配置只注入指定的chunks,這樣就不會把其餘頁面的js也加載進來,致使找不到對應的html模版,也優化了加載。
if (pathname in baseWebpackConfig.entry) {
   //這裏配置當前單頁須要加載的chunks
    conf.chunks = ['manifest', 'vendor',pathname];
    conf.hash = true;
   }
複製代碼
  1. 多單頁命名問題 多單頁面vue應用根元素的id不能相同, 不然會出現頁面互相覆蓋的問題。
new Vue({
    //根元素id
     el: '#app',
     components: { App },
     template: '<App/>'
    })
複製代碼
  1. css 究竟是 import 仍是 require 兩種都是模塊引入的方式,import使es6規範,require是commonJS規範,須要注意的是import會有提高效果,可能出現import覆蓋require樣式。
require('/style.css');
import '/style.css';
複製代碼
  1. 多單頁之間vuex數據不能共享 單頁應用之間vuex數據是不能共享的,由於其本質仍是多頁應用。頁面與頁面之間的數據傳遞仍是要經過URL傳參數或者經過緩存讀取。這在必定程度上仍是增長了應用複雜度,因此在業務粒度的拆分上不能太細,儘可能保證在單個業務流程是在一個單頁內,數據能夠共享。github

  2. 考慮後續部署的問題 單頁應用的部署很簡單,只有一個html文件,採起多單頁的方案,必需要提早跟運維溝通後續部署的問題,確保能實現平穩過渡。web

相關文章
相關標籤/搜索