1. 程式人生 > >前後端分離之vue2.0+webpack2 實戰專案 -- html模板拼接

前後端分離之vue2.0+webpack2 實戰專案 -- html模板拼接

對於前後端分離,如何把一個頁面的公共部分比如head, header, footer, content等組合成一個完整的html 是一個值得考慮的地方。

對於php,我們可以利用include載入其他頁面,像yii框架,可以利用render將輸出的內容嵌入到父模板,從而形成一個完整的頁面。

那對於純靜態的html我們如何拼接呢?

可以想到市面上的多種模板引擎,比如artTemplate, doT, ejs等,他們可以使用require或include等特殊標記的語法來引入其他模組。但如果每個頁面我們都去寫若干個require,比如:

require('head.html')
require('header.html')
...
require(
'side-bar.html') require('footer.html')

是不是略顯麻煩?另外head內的title如何自定義?對於要求head內根據不同頁面有不同引用的icon或者css甚至js,該如何配置呢?

這時我們就想著去尋找一套自動化的拼接和可配置的靈活方案,html-webpack-plugin 就可以幫我們完成這些。

複製程式碼
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpackConfig = {
  entry: 'index.js',
  output: {
    path: 'dist',
    filename: 
'bundle.js' }, plugins: [   new HtmlWebpackPlugin(       title: 'this is mytitle a',       _html: 'this is content a.',          filename: 'index.html', template: 'index.ejs',   )   ], };
複製程式碼

html-webpack-plugin的基本使用方法如上,它可以把模板template index.ejs轉化成html,命名為index.html,並把bundle.js引入index.html。

html-webpack-plugin預設集成了ejs模板引擎,所以我們可以直接使用ejs模板。當然我們也可以引入其他模板,包括handlebars等都可以使用。

title,  _html為自定義的一些屬性,你還可以增加比如content, data等等你想要的資料傳到模板。傳到模板後,ejs可以直接獲取到傳過來的值,獲取方法如下:

複製程式碼
<!-- index.ejs -->

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
    <header style="text-align:center;color:#fff;font-size:20px;background:#333;">
        this is header.
    </header>

    <%= htmlWebpackPlugin.options._html %>

    <section id="app"></section>

    <footer style="text-align:center;color:#fff;font-size:20px;background:#333;">
        this is footer.
    </footer>
    <script src="./dist/build.js"></script>
</body>
</html>
複製程式碼

 <%= %> 用來引入變數

 <% %> 用來執行js判斷語句

這樣我們就可以自定義一些內容輸入到模板頁面中,但我們如果有很多個模板,如何挨個生成呢?

官網給出的解決方案就是有幾個模板就宣告幾次外掛:

複製程式碼
plugins: [
  new HtmlWebpackPlugin(
      title: 'this is mytitle a',
      _html: 'this is content a.',      
      filename: 'index_a.html',
          template: 'index_a.ejs',
    ),
      new HtmlWebpackPlugin(
      title: 'this is mytitle b',
      _html: 'this is content b.',      
      filename: 'index_b.html',
          template: 'index_b.ejs',
    ),
       new HtmlWebpackPlugin(
      title: 'this is mytitle c',
      _html: 'this is content c.',      
      filename: 'index_c.html',
          template: 'index_c.ejs',
    )
  ],
複製程式碼

多個模板的問題解決了,但對於每個模板內部,如何抽離出公共部分(head等),我們每次寫頁面只關注內容部分呢?

正式構建模板佈局框架

既然html-webpack-plugin的template可以接受多個模板,那我們也可以傳給它一個js,只要js返回一個模板檔案就可以,這樣我們拼接的工作都可以用js和ejs完成。

在此之前我們說下html-webpack-plugin的 chunks 屬性

複製程式碼
{
  entry: {
      a: './a.js',
      b: './b.js',
      c: './c.js'
  },
  output: {
    path: 'dist',
    filename: 'js/[name].js'
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'My App',
      filename: 'assets/admin.html',
      chunks: ['a','b']      
    })
  ]
}
複製程式碼

chunks: 規定需要引入的模組。在這裡例子中,只有a和b被插入到html中,c並不會被引入。

ok,接下來我們就可以針對不同的模板指定引入不同的js了。

先看下流程(如下示意圖),假如現在要做income.html頁面,我們只關注income.ejs,它是body中的內容部分,html-webpack-plugin 的 template 為 html/income.js,它會把我們的頁面內容 income.ejs 傳給 html/layout.js,在 layout.js 內,我們會引入html的各個公共部分,並把html/income.js 中定義的各種引數傳給頁面的各個部分,然後把這些公共部分傳給 html/layout.ejs 組合並返回。html-webpack-plugin 就把返回的完整的模板轉化為 目標html

程式碼如下:

複製程式碼
/***** 生成組合後的html *****/

var pages = getEntry('./html/src/**/*.ejs')
for (var pathname in pages) {
    var conf = {
        filename: path.resolve(__dirname, './html/dist/' + pathname + '.html'), // html檔案輸出路徑
        template: path.resolve(__dirname, './html/src/' + pathname + '/' + pathname + '.js'), // 模板路徑
        inject: true, 
        cache: true, //只改動變動的檔案
        minify: {
            removeComments: true,
            collapseWhitespace: false
        }
    }
    if (pathname in module.exports.entry) {
        conf.chunks = [pathname, 'vendors', 'manifest']
    }

    module.exports.plugins.push(new htmlWebpackPlugin(conf))
}
複製程式碼

inject: ture/body 將js引用插入到body內,head將js引用插入到head內,false為不插入

cache:是否值編譯改動的檔案

minify: 壓縮html

  removeComments: 去除註釋

  collapseWhitespace: 去除空格

chunks: 自動引入公共模組 js 以及 當前 pathname 對應的 js 檔案

template: 為入口js檔案對應的用於拼接模板的js

這個js就有點像php的controller,可以定義當前頁面的title等資訊,並規定使用哪個ejs模板進行拼接

複製程式碼
/* html/income/income.js */

const content = require('./income.ejs') //使用income.ejs模板進行拼接 const layout = require('../layouts/layout.js') const pageTitle = '訊息通知' //自定義頁面title並傳給 layoutjs 分發給頁面的公共模組 module.exports = layout.init(pageTitle).run(content({ pageTitle }))
複製程式碼

 layout.js則引入各個公共模組,給他們傳入需要的引數,並返回layout.ejs拼接後的結果

複製程式碼
/* html/layout/layout.js */

const layout = require('./layout.ejs')
const header = require( './header.ejs') // 頁頭的模板
const footer = require('./footer.ejs') // 頁尾的模板
const topNav = require('./top-nav.ejs') // 頂部欄的模板
const sideMenu = require('./side-menu.ejs') // 側邊欄的模板

/* 整理渲染公共部分所用到的模板變數 */

const pf= {
    pageTitle: ''
}
const moduleExports = {
  /* 處理各個頁面傳入而又需要在公共區域用到的引數 */
    init(pageTitle) {
        pf.pageTitle = pageTitle // 比如說頁面名稱,會在<title>或麵包屑裡用到
    
        //console.log('pf.pageTitle'+pf.pageTitle)

        return this
    },
  /* 整合各公共元件和頁面實際內容,最後生成完整的HTML文件 */
    run(content) {
        const renderData = {
            header: header(),
            footer: footer(),
            topNav: topNav(pf),
            sideMenu: sideMenu(),
            content: content,
        }
        return layout(renderData)
    },
}

module.exports = moduleExports
複製程式碼

layout.ejs 為終極模板,引入各個公共模組變數

複製程式碼
<!-- html/layout/layout.ejs -->

<!DOCTYPE html>
<html>
<head>
    <title>vue</title>
</head>
<body>

    <%= header %>
    <div id="wrapper">
      <%= topNav %>
      <%= sideMenu %>
      <%= content %>
    </div>
    <%= footer %>
</body>
</html>
複製程式碼

OK,到這裡我們基本可以完成功能了,對每個新頁面我們只需要關注這個頁面的body部分,以及一個頁面控制器 js 即可。無需在頁面引入 css 和 js ,html-webpack-plugin會自動根據模板命名找到對應的js檔案引入到html中,而css就只需要在相應的js檔案中引入即可。

前後端分離的html拼接也就完成了。

目錄結構參考:

相關推薦

前後分離vue2.0+webpack2 實戰專案 -- html模板拼接

對於前後端分離,如何把一個頁面的公共部分比如head, header, footer, content等組合成一個完整的html 是一個值得考慮的地方。對於php,我們可以利用include載入其他頁面,像yii框架,可以利用render將輸出的內容嵌入到父模板,從而形成一個

前後分離mockjs基本介紹

body pos mock 響應 func 正則 str 整數 fun 安裝與使用 # 安裝 npm install mockjs #使用 Mock var Mock = require(‘mockjs‘) var data = Mock.mock({ // 屬性

前後分離VueJS前端

程式碼:https://github.com/jimolonely/vue-jwt-demo 前言 前端用什麼框架都可以,這裡選擇小巧的vuejs。 要實現的功能很簡單:  1、登入功能,成功將伺服器返回的token存在本地  2、使用帶token的header訪問伺服器

前後分離Java後

前後端分離的思想由來已久,不妨嘗試一下,從上手開始,先把程式碼寫出來再究細節。 程式碼下載:https://github.com/jimolonely/AuthServer 前言 以前服務端為什麼能識別使用者呢?對,是session,每個session都存在服務端,瀏覽器每次請求都帶著ses

[django]前後分離JWT使用者認證

在前後端分離開發時為什麼需要使用者認證呢?原因是由於HTTP協定是不儲存狀態的(stateless),這意味著當我們透過帳號密碼驗證一個使用者時,當下一個request請求時它就把剛剛的資料忘了。於是我們的程式就不知道誰是誰,就要再驗證一次。所以為了保證系統安全,我們就需要驗證使用者否處於登入狀態。 傳統方

前後分離介面定義滯後帶來的問題

   前言:   目前正參與我司一個後臺管理型專案,我司採取的是前後端分離開發,後端採用dubbo框架提供介面,前端整合egg.js和dubbo.js;各司其職,我和一道友專門負責前端伺服器整個模組,伺服器搭建探索過程費了點時間(也不太多),然後就前端頁面的排期,給我的模組排了

Spring Boot企業級開發前後分離博客系統+Thymeleaf實戰+Jpa數據持久化實戰+全文檢索實戰+架構設計與分層+API設計

聲明 thymeleaf 項目 sys eat 設計 article serve tis 前端項目名為wh-web後端項目名為wh-server項目展示地址為我的github pages(https://smallsnail-wh.github.io)用戶名:admin,密

前後分離SpringBoot專案Token認證

寫在開始 有人說,愛上一座城,是因為城中住著某個喜歡的人。其實不然,愛上一座城,也許是為城裡的一道生動風景,為一段青梅往事,為一座熟悉老宅。或許,僅僅為的只是這座城。就像愛上一個人,有時候不需要任何理由,沒有前因,無關風月,只是愛了。 —林徽因   前段時間,大體

Django前後分離域名配置

編輯檔案  sudo vim /etc/hosts 將兩個域名新增到檔案中 127.0.0.1 api.xxxx.site 127.0.0.1 www.xxxx2.site  前端xxxx/js目錄中,建立host.js檔案用以為前端儲存後端域名 var h

基於小程式開發的前後分離登入狀態

公司接了一個小程式的活。本來後臺想用的是session儲存登入狀態。後來發現登入存進去的sessionId和取時候的sessionId不一樣,匯入無法取到登入狀態,百度了一下才知道,原來是小程式端不支援儲存cookie,後來想到了在微信登入授權後,把openId加密(token),當做key,ope

前後分離_後_分類導航功能_就是_三級分類,表是無限極的設計

需求: 1. 資料庫 設計原則:無限極分類 2, 介面 3,實現 3.1 pojo 3.2, dao 我用的是mybatis 3.3,service 用的example多條件查詢 public List<Categ

前後分離SEO優化--------以vue為例

   前言----SEO是由英文Search Engine Optimization縮寫而來, 中文意譯為“搜尋引擎優化”。SEO是指通過對網站進行站內優化和修復(網站Web結構調整、網站內容建設、網站

springboot前後分離跨域

springmvc有多種處理跨域的方法,介紹最簡單的一種: @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addCors

【Web】JavaWeb專案為什麼我們要放棄jsp?為什麼要前後解耦?為什麼要前後分離?2.0版,為分散式架構打基礎。

前戲 前後端分離已成為網際網路專案開發的業界標準使用方式,通過nginx+tomcat的方式(也可以中間加一個nodejs)有效的進行解耦, 並且前後端分離會為以後的大型分散式架構、彈性計算架構、微服務架構、多端化服務(多種客戶端,例如:瀏覽器,車載終端,安卓,IOS等等

前後分離Vue(三)爬過得那些坑

爬過得那些坑前言:在整個Vue的過程中,遇到了不少坑。查詢不同的資料,把這些坑給填了,記錄下這些坑,以及解決辦法。一、Http請求的那些坑1.不支援http請求表現為:程式啟動正常,點選按妞不跳轉,後臺無響應,瀏覽器調試出現Uncaught TypeError: Cannot

前後分離JWT使用者認證

在前後端分離開發時為什麼需要使用者認證呢?原因是由於HTTP協定是不儲存狀態的(stateless),這意味著當我們透過帳號密碼驗證一個使用者時,當下一個request請求時它就把剛剛的資料忘了。於是我們的程式就不知道誰是誰,就要再驗證一次。所以為了保證系統安全,我們就需要驗證使用者否處於登入狀態。傳統方式前

前後分離Springboot後

這是上一篇部落格前後端分離之Java後端的重寫. 原始碼 前後端分離的後端主要解決的就2個問題 : 跨域訪問(CORS)和token校驗,下面快速說明. 1.專案環境 使用Intellij IDE. 專案結構: 2.跨域訪問 解決跨域很簡單,翻

前後分離session問題

背景目前正在開發的專案是前後端分離的專案,前端是react,後端springboot開發的微服務,在除錯登入的時候發現,登入成功後把所需的資訊都放到session中並存到redis裡,但當用戶從session中取資訊的時候發現始終取不到,每次跨域請求時ajax傳送的都是新的s

從壹開始前後分離 [ Vue2.0+.NET Core2.1] 二十一║Vue實戰:開發環境搭建【詳細版】

緣起  哈嘍大家好,兜兜轉轉終於來到了Vue實戰環節,前邊的 6 篇關於Vue基礎文章我剛剛簡單看了看,感覺寫的還是不行呀,不是很系統,所以大家可能看上去比較累,還是得抽時間去潤潤色,修改修改語句和樣式,至少也得對得住粉絲哈,應該給部落格園官方提個小建議,要是能允許好友或者其他人修改文章的功能就好了,比如百

從壹開始前後分離【 .NET Core2.0 +Vue2.0 】框架十二 || 三種跨域方式比較,DTOs(資料傳輸物件)初探

更新反饋 1、博友@童鞋說到了,Nginx反向代理實現跨域,因為我目前還沒有使用到,給忽略了,這次記錄下,為下次補充。 程式碼已上傳Github+Gitee,文末有地址   今天忙著給小夥伴們提出的問題解答,時間上沒把握好,都快下班了,趕緊釋出:書說上文《從壹開始前