vue開發多頁面應用 - hash模式和history模式


我們知道vue可以快速開發web單頁應用,而且官方為我們提供了自己的應用腳手架vue-cli,我們只需要下載腳手架,安裝依賴后就可以啟動vue應用雛形。

這得益與webpack的依賴追蹤,各種資源后綴的loader,以及相關webpack插件的強大功能。

然而有些時候,我們有多頁面的開發需求,在這種情況下,我們可以為多頁面構建相應的多個應用,比如通過vue-cli生成多個應用目錄,但是這樣一方面會多出很多重復的構建代碼和樣板代碼,另外也會破壞應用的統一性,不便於維護。我們可以在vue-cli的基礎上通過修改webpack配置來讓腳手架具備構建多頁應用的能力。

webpack在打包編譯vue文件時,最重要的是入口和輸出的配置、所以我們會主要修改這兩個部分的配置。

我的個人博客就是一個vue多頁應用,包含客戶端和后台管理兩個部分,下面就以它為例子來說明如何實現vue多頁應用,整個過程是基於vue-cli2的。

入口配置

入口配置比較簡單,打開webpack.base.conf.js,只需要修改entry配置就可以了,修改如下:

entry: {
    client:  ["babel-polyfill", "./src/Client/main.js"],
    manager: ["babel-polyfill", "./src/Manager/main.js"],
},

增加babel-polyfill主要是兼容低版本瀏覽器,因為Babel默認只轉換新的JavaScript句法(syntax),而不轉換新的API,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局對象,以及一些定義在全局對象上的方法(比如Object.assign)都不會轉碼。

輸出配置

輸出配置要分別配置開發環境以及生產環境的輸出,我們先來配置開發環境。打開webpack.dev.conf.js,在plugin配置項中添加以下配置,並刪除原來的HtmlWebpackPlugin配置。

new HtmlWebpackPlugin({
      filename: 'client.html',
      template: './tpl/index.html',
      inject: true,
      chunks: ['client'],
}),
new HtmlWebpackPlugin({
      filename: 'manager.html',
      template: './tpl/index.html',
      inject: true,
      chunks: ['manager'],
}),

可以看到,這里使用HtmlWebpackPlugin插件配置了兩份html輸出,fliename是編譯輸出的文件名,template是html模版,不同頁面可以使用相同的模版也可以使用不同的模版。

實際上,開發環境下我們訪問的頁面資源是被webpack管理在內存中的,webpack-dev-server作為本地服務根據url返回內存資源給瀏覽器從而呈現頁面。但是多頁面情況下如何去根據url返回對應的頁面呢,答案就是配置devServer下的historyApiFallback,該配置項會傳遞給 connect-history-api-fallback這個中間件,對request請求的url進行重定向,避免開發環境下頁面404,配置如下:

historyApiFallback: {
     rewrites: [
        { from: 'index', to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
        { from: /\/admin/, to: path.posix.join(config.dev.assetsPublicPath, 'admin.html') },
      ],
 },

到這里開發環境的配置就完成了,npm start啟動項目后,使用localhost:8080可以看到客戶端頁面,使用localhost:8080/admin可以看到后台管理頁面。

接下來對生產環境進行配置,首先打開config/index.js, 在build配置項中增加目標html的輸出路徑及名稱。

    index: path.resolve(__dirname, '../server/public/index.html'),
    admin: path.resolve(__dirname, '../server/public/admin.html'),

接下來打開build/webpack.prod.conf.js,在pulgin中添加以下配置:

new HtmlWebpackPlugin({
      filename: config.build.index,
      template: './tpl/index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
      },

      chunksSortMode: 'dependency',
      chunks: ['manifest', 'vendor', 'client']
}),

new HtmlWebpackPlugin({
      filename: config.build.admin,
      template: './tpl/index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
      },
        chunksSortMode: 'dependency',
        chunks: ['manifest', 'vendor', 'manager']
}),

這個地方要特別注意的是一定要配置chunks,否則所有打包后的文件將同時引入admin.html和index.html。

這樣,整個vue多頁面配置就完成了。我們可以看到,如果項目中每增加一個一級頁面,就需要多處修改webpack配置,很繁瑣。為此,更好的方式是基於vue-cli2進行一層封裝,這是我寫的一個擴展示例multiPage-vue-cli

 
        

history模式

有的時候出於強迫症,不能忍受hash模式下的url上存在#符號,或者是出於業務需求,url不能帶#號。這個時候要考慮采用vue-router的history模式,history模式的前端配置與上文大同小異,但是由於history模式下url路徑的跳轉是vue-router利用h5的history API動態添加的,而手動刷新頁面會導致找不到路由從而產生404錯誤,因此還需要對服務端進行配置,將路由重定向到一級頁面。比如可以對nginx作如下配置:

server {
       listen 80;

       location ^~ /api {
          proxy_pass http://127.0.0.1:3000;
       }

       location /admin {
          root  /home/silentport.github.io/nginx/blog/;
          index admin.html;
          try_files $uri $uri/ /admin.html;
       }
       location / {
          root /home/silentport.github.io/nginx/blog;
          index index.html;
          try_files $uri $uri/ /index.html;
       }   
}

其中,

第一個配置是將所有的以/api開頭的請求轉發到node服務器處理;
第二個配置是將所有/admin開頭的請求重定向到admin.html;
第三個配置是將所有的不是以api和admin開頭的請求重定向到index.html,root的配置還可以響應頁面的靜態文件;

 

這樣一來客戶端訪問就沒什么問題了,刷新頁面也不會404,一切正常,但是管理端訪問依然存在問題,問題是出在當在admin.html中做路由切換,並手動刷新的時候,url中的admin消失,這樣一來nginx會將它重定向到客戶端的頁面。針對這個問題,還需要在admin的頁面中對vue-router增加一個base配置項,讓路由跳轉的時候url始終攜帶這個base,配置如下:

export default new Router({
  mode: 'history',
  base: '/admin',
  routes: [
    
  ]
})

經過上述所有的配置以后,history模式就可以正常使用了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM