eggjs+nunjucks前后端分離seo友好的前端靜態(tài)頁面

利用egg.js腳手架項目初始化

公司需要做公司的一個官網(wǎng)項目砰琢,需要做seo迈勋,之前使用nuxt.js框架勉耀,后期感覺雖然基于vue.js框架來書寫代碼很方便,但是在一些配置方便感覺很不爽粗蔚,在源碼中會渲染一些數(shù)據(jù)源的東西尝偎,很亂,所以這次選擇使用egg.js+nunjucks的渲染方式,基礎(chǔ)數(shù)據(jù)處理還是后端java提供服務(wù)致扯,然后通過本框架獲取后端數(shù)據(jù)肤寝,在通過模板渲染,發(fā)現(xiàn)nunjuck的模板渲染功能十分強大且優(yōu)秀抖僵,也十分方便鲤看。egg.js提供的egg-bin模塊也十分強大,處理能力極強耍群,且省去了pm2的監(jiān)聽守護(hù)义桂,用起來十分方便。下面介紹一下怎么使用這些技術(shù)搭建一個自己的框架蹈垢。

這里是項目地址慷吊,歡迎大家指正。

  • 首先創(chuàng)建一個文件目錄并切換至該目錄
    mkdir egg-njk && cd egg-njk
  • 項目初始化
    npm init egg --type=simple
  • 安裝項目必要插件
    npm i
  • 項目啟動
    開發(fā):npm run dev
    生產(chǎn):npm run start
    停止:npm run stop

使用egg-view-nunjucks插件

  • 安裝egg-view-nunjucks
    npm i egg-view-nunjucks --save
  • 使用插件
    // config/plugin.js
    'use strict';

    /** @type Egg.EggPlugin */
    
    const nunjucks = {
      enable: true,
      package: 'egg-view-nunjucks',
    };
    module.exports = {
      nunjucks,
      // had enabled by egg
      // static: {
      //   enable: true,
      // }
    };

    
    // config/config.default.js
    // 添加 view 配置
    config.view = {
        defaultViewEngine: 'nunjucks',
        mapping: {
          '.tpl': 'nunjucks',
        },
    };
  • 創(chuàng)建一個controller

使用vscode插件庫提供的eggjs插件能快速的生成代碼結(jié)構(gòu)

    // app/controller/home.js
    'use strict';

    const Controller = require('egg').Controller;
    
    class HomeController extends Controller {
      async index() {
        const { ctx } = this;
        const text = '首頁';
        await ctx.render('home.tpl', { text });
      }
    }
    
    module.exports = HomeController;
  • 創(chuàng)建一個頁面模板
    // app/view/home.tpl
    
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>首頁</title>
        </head>
        <body>
            <div>{{text}}</div>
        </body>
    </html>

此時啟動項目,已經(jīng)可以看到一個頁面,下面我們來看看nunjucks怎么用曹抬?

nunjucks使用

  • 創(chuàng)建項目模板
    <!--app/view/layout/layout.tpl-->
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            {% block description %}
                <meta name="description" itemprop="description" content="description繼承">
            {% endblock %}
            {% block keywords %}
                <meta name="keywords" content="keywords繼承">
            {% endblock %}
            {% block stylesheet %}{% endblock %}
            <title>{% block title %} egg-huk {% endblock %}</title>
        </head>
        <body>
            <div id="header">
                {% block header %} {% endblock %}
            </div>
            <div id="main">
                {% block main %} {% endblock %}
            </div>
            <div id="footer">
                {% block footer %} {% endblock %}
            </div>
        </body>
        {% block script %}{% endblock %}
    </html>
  • 創(chuàng)建公共模塊
    <!--app/view/commons/header.tpl-->
    <div>頭部</div>
    
    <!--app/view/commons/footer.tpl-->
    <div>底部</div>
  • 修改home.tpl以使用模板繼承
    <# app/view/home.tpl #>
    {# 繼承自全局的layout模板 #}
    {% extends "./layout/layout.tpl" %}
    {# 獨立引入的css #}
    {% block stylesheet %}{% endblock %}
    {# header #}
    {% block header %}
      {% include "./commons/header.tpl" %}
    {% endblock %}
    {# 頁面主體 #}
    {% block main %}
        <div>
            <span>{{text}}</span>
        </div>
    {% endblock %}
    {# header #}
    {% block footer %}
      {% include "./commons/footer.tpl" %}
    {% endblock %}
    {% block script %}{% endblock %}

如果需要使用到css溉瓶、js、images等文件谤民,需要在public文件夾下創(chuàng)建文件/文件夾 然后在模板中引入嚷闭,layout文件中引入公共css/js模塊,在.tpl文件中通過繼承引入各自獨立的css/js文件

  • layout.tpl 引入公共模塊
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        {% block description %}
            <meta name="description" itemprop="description" content="description繼承">
        {% endblock %}
        {% block keywords %}
            <meta name="keywords" content="keywords繼承">
        {% endblock %}
        <link rel="stylesheet" href="/public/css/reset.min.css">
        <link rel="stylesheet" href="/public/css/animate.min.css">
        <link rel="stylesheet" href="/public/css/bootstrap.min.css">
        {% block stylesheet %}{% endblock %}
        <title>{% block title %} egg-huk {% endblock %}</title>
    </head>
    <body>
        <div id="header">
            {% block header %} {% endblock %}
        </div>
        <div id="main">
            {% block main %} {% endblock %}
        </div>
        <div id="footer">
            {% block footer %} {% endblock %}
        </div>
    </body>
        <script src="/public/js/jquery-3.4.1.min.js"></script>
        <script src="/public/js/bootstrap.min.js"></script>
        {% block script %}{% endblock %}
    </html>
  • home.tpl中繼承獨立的文件
    {# 繼承自全局的layout模板 #}
    {% extends "./layout/layout.tpl" %}
    {# 獨立引入的css #}
    {% block stylesheet %}
        <link rel="stylesheet" href="/public/css/home.min.css">
    {% endblock %}
    {# header #}
    {% block header %}
      {% include "./commons/header.tpl" %}
    {% endblock %}
    {# 頁面主體 #}
    {% block main %}
        <div class="content">
            <span>{{text}}</span>
        </div>
    {% endblock %}
    {# header #}
    {% block footer %}
      {% include "./commons/footer.tpl" %}
    {% endblock %}
    {% block script %}
        <script src="/public/js/home.js"></script>
    {% endblock %}

egg.js遵循mvc模式赖临,數(shù)據(jù)處理請放在service文件中

    // app/config/default.js
    
    // add you api config here
    // config.api = 'https://xxx.xxxx.com/';
    
    // app/service/home.js
    'use strict';

    const Service = require('egg').Service;
    
    class HomeService extends Service {
      async getList() {
        // const { config } = this;
        // const api = config.api;
        // console.log(api);
        const userList = [
          {
            name: 'leehan',
            age: 22,
            sex: 1,
          },
          {
            name: 'spider man',
            age: 16,
            sex: 1,
          },
          {
            name: '猩紅女巫',
            age: 20,
            sex: 2,
          },
          {
            name: '滅霸',
            age: 40,
            sex: null,
          },
        ];
        return userList;
      }
    }
    
    module.exports = HomeService;

  • 在controller中調(diào)用
    'use strict';

    const Controller = require('egg').Controller;
    
    class HomeController extends Controller {
      async index() {
        const { ctx, service } = this;
        const userList = await service.home.getList();
        await ctx.render('home.tpl', { userList });
      }
    }
    
    module.exports = HomeController;
  • 在頁面中渲染數(shù)據(jù)
    {# 繼承自全局的layout模板 #}
    {% extends "./layout/layout.tpl" %}
    {# 獨立引入的css #}
    {% block stylesheet %}
        <link rel="stylesheet" href="/public/css/home.min.css">
    {% endblock %}
    {# header #}
    {% block header %}
      {% include "./commons/header.tpl" %}
    {% endblock %}
    {# 頁面主體 #}
    {% block main %}
        <ul class="content">
            {% for item in userList %}
                <li>
                    <i>序號</i>:<span>{{loop.index}}</span>
                    <i>姓名</i>:<span>{{item.name}}</span>
                    <i>年齡</i>:<span>{{item.age}}</span>
                    <i>性別</i>:<span>{{item.sex | getSex}}</span>
                </li>
            {% endfor %}
        </ul>
    {% endblock %}
    {# header #}
    {% block footer %}
      {% include "./commons/footer.tpl" %}
    {% endblock %}
    {% block script %}
        <script src="/public/js/home.js"></script>
    {% endblock %}

框架地址:egg-njk 如果需要可以下載之后改一改直接使用

==注意:== 項目中想要引入sass進(jìn)行編譯胞锰,但是沒有找到好的方法,所以使用了vscode的easy-sass插件進(jìn)行編譯兢榨,如果哪位了解這里應(yīng)該怎么使用sass進(jìn)行實時編譯嗅榕,希望能獲得您的指點。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吵聪,一起剝皮案震驚了整個濱河市凌那,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吟逝,老刑警劉巖帽蝶,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異块攒,居然都是意外死亡励稳,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門囱井,熙熙樓的掌柜王于貴愁眉苦臉地迎上來驹尼,“玉大人,你說我怎么就攤上這事庞呕⌒卖幔” “怎么了程帕?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長地啰。 經(jīng)常有香客問我愁拭,道長,這世上最難降的妖魔是什么亏吝? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任敛苇,我火速辦了婚禮,結(jié)果婚禮上顺呕,老公的妹妹穿的比我還像新娘。我一直安慰自己括饶,他們只是感情好株茶,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著图焰,像睡著了一般启盛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上技羔,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天僵闯,我揣著相機與錄音,去河邊找鬼藤滥。 笑死鳖粟,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拙绊。 我是一名探鬼主播向图,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼标沪!你這毒婦竟也來了榄攀?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤金句,失蹤者是張志新(化名)和其女友劉穎檩赢,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體违寞,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡贞瞒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了趁曼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片憔狞。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖彰阴,靈堂內(nèi)的尸體忽然破棺而出瘾敢,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布簇抵,位于F島的核電站庆杜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏碟摆。R本人自食惡果不足惜晃财,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望典蜕。 院中可真熱鬧断盛,春花似錦、人聲如沸愉舔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽轩缤。三九已至命迈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間火的,已是汗流浹背壶愤。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留馏鹤,地道東北人征椒。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像湃累,于是被迫代替她去往敵國和親陕靠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容