iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 4
0
Modern Web

Webpack with ASP.NET MVC系列 第 4

使用 Html-Webpack-Plugin 引入 Bundle 檔案

為了把打包完的檔案引入頁面,我們透過 Html-Webpack-Plugin 來產生 Partial View 並引入打包檔案。Views 資料夾底下新增 BundleTemp 資料夾,使用 BundleTemp/_JsTemplate.cshtml 為模板來產生引入 JS 檔案的頁面。同樣的,以 BundleTemp/_CssTemplate.cshtml 為模板來產生引入 CSS 檔案的頁面,最後透過 Html-Webpack-Plugin 將 Partial View 產生到 Views/Bundle 資料夾。

Views 資料夾結構

  ┝╸ Views
     ┝╸ BundleTemp
        ┝╸ _JsTemplate.cshtml
        ┝╸ _CssTemplate.cshtml
     ┝╸ Account
        ┝╸ Profile.cshtml
        ┝╸ Login.cshtml
        ┕╸ Register.cshtml
     ┝╸ Cart
        ┝╸ Checkout.cshtml
        ┕╸ Complete.cshtml
     ┝╸ Home
        ┕╸ Home.cshtml
     ┝╸ Member
     ┝╸ Order
     ┕╸ Product

安裝 Html-Webpack-Plugin 套件

npm i Html-Webpack-Plugin --save-dev

一般來說,Webpack 會設定如下:

var HtmlWebpackPlugin = require('html-webpack-plugin')  
module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'Views/Bundle/_Home.bundle.html',
      template: 'Views/BundleTemp/_JsTemplate.cshtml',
      chunks: ['Home'],
      inject: false,
    })
  ]
}  

BundleTemp/_JsTemplate.cshtml 裡則使用 ejs 的語法來接 chunks 參數

BundleTemp/_JsTemplate.cshtml
<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
  <script src="<%=htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
<%}%>
BundleTemp/_CssTemplate.cshtml
<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
  <link rel="stylesheet" href="<%=htmlWebpackPlugin.files.chunks[chunk].css %>"></link>
<%}%>

透過 Html-Webpack-Plugin 產生的 Partial View Views/Bundle/Home_Js.bundle.cshtml,就會引入 Home.bundle.js,而 Views/Bundle/Home_Css.bundle.cshtml,就會引入 Home.css

Views/Bundle/Home_Js.bundle.cshtml
<script type="text/javascript" src="/Resource/Bundle/Home.bundle.js>"></script>
Views/Bundle/Home_Css.bundle.cshtml
<link rel="stylesheet" href="/Resource/Bundle/Css/Home.css>"></link>

由於專案是多入口頁面,所以我們同樣使用 glob 這個方法來查找 Views 底下的資料夾,並結合 Html-Webpack-Plugin 動態生成 Partial View。

使用 glob 自動查找 Views 資料夾

/**
 * @class setPartialView
 * @description 動態生成 Partial View,並引入該頁相關 Bundle 檔案
 */
setPartialView = function() {
  var TargetPage = glob.sync('Views/*/')
  var JsTemplate = 'Views/BundleTemp/_JsTemplate.cshtml'
  var CssTemplate = 'Views/BundleTemp/_CssTemplate.cshtml'
  var getPath = FileName => `./../../Views/Bundle/${FileName}.bundle.cshtml`
  TargetPage.forEach(filePath => {
    var BundleName = filePath.split('/')[1]
    if (BundleName === 'BundleTemp' || BundleName === 'Bundle') return false
    var JsFileName = getPath(BundleName + '_Js')
    var CssFileName = getPath(BundleName + '_Css')
    CommonConfig.plugins.push(
      new HtmlWebpackPlugin({
        template: JsTemplate,
        filename: JsFileName,
        chunks: [BundleName],
        inject: false,
      })
    )
    CommonConfig.plugins.push(
      new HtmlWebpackPlugin({
        template: CssTemplate,
        filename: CssFileName,
        chunks: [BundleName],
        inject: false,
      })
    )
  })
}
var CommonConfig = {
  entry: getEntry(),
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'Resource/Bundle')
  }
}
setPartialView()   // 生成 Partial View
module.exports = CommonConfig

最後生成的 Partial View

  ┝╸ Views
     ┝╸ Bundle
        ┝╸ Account_Js.bundle.cshtml
        ┝╸ Account_Css.bundle.cshtml
        ┝╸ Cart_Js.bundle.cshtml
        ┝╸ Cart_Css.bundle.cshtml
        ┝╸ Home_Js.bundle.cshtml
        ┝╸ Home_Css.bundle.cshtml
        ┝╸ Member_Js.bundle.cshtml
        ┝╸ Member_Css.bundle.cshtml
        ┝╸ Order_Js.bundle.cshtml
        ┝╸ Order_Css.bundle.cshtml
        ┝╸ Product_Js.bundle.cshtml
        ┝╸ Product_Css.bundle.cshtml
     ┝╸ Account
     ┝╸ Cart
     ┝╸ Home
     ┝╸ Member
     ┝╸ Order
     ┕╸ Product

最後在 cshtml 使用 @Html.Partial

// section styles 引入在 <head>
@section styles {
  @Html.Partial("~/Views/Bundle/_Home_Css.bundle.cshtml")
}

// section scripts 引入在 </body> 上方
@section scripts {
  @Html.Partial("~/Views/Bundle/_Home_Js.bundle.cshtml")
}

Github DEMO


上一篇
ASP.NET MVC 專案架構及入口頁面設定
下一篇
將 Module 暴露到全域
系列文
Webpack with ASP.NET MVC30

尚未有邦友留言

立即登入留言