成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Node中間層實(shí)踐(二)——搭建項(xiàng)目框架

DrizzleX / 3367人閱讀

摘要:項(xiàng)目地址腳手架使用過(guò),的同學(xué)都清楚,官方推薦的安裝方式是通過(guò)專用的來(lái)快速搭建一個(gè)由編譯打包的項(xiàng)目框架。用在層的模塊化,在中間層實(shí)現(xiàn)了模塊化。這樣,從中間層到前端都實(shí)現(xiàn)了熱加載。

版權(quán)聲明:更多文章請(qǐng)?jiān)L問(wèn)我的個(gè)人站Keyon Y,轉(zhuǎn)載請(qǐng)注明出處。

項(xiàng)目地址:https://github.com/KeyonY/NodeMiddle

腳手架?

使用過(guò)angular2,vue2的同學(xué)都清楚,官方推薦的安裝方式是通過(guò)專用的angular-cli、vue-cli來(lái)快速搭建一個(gè)由webpack編譯、打包的項(xiàng)目框架。

受這兩個(gè)工具的啟發(fā),我在項(xiàng)目之初開(kāi)發(fā)一個(gè)基于webpack的項(xiàng)目框架:

使用express搭載webpack-dev-middleware和webpack-hot-middleware進(jìn)行熱加載

內(nèi)置dev(開(kāi)發(fā)環(huán)境)和 production(生產(chǎn)環(huán)境)兩種啟動(dòng)方式

技術(shù)選型 node開(kāi)發(fā)框架

express和koa二選一。

express的更貼近Web Framework這一概念;

express功能極簡(jiǎn),完全是由路由和中間件構(gòu)成一個(gè)的 web 開(kāi)發(fā)框架:從本質(zhì)上來(lái)說(shuō),一個(gè) Express 應(yīng)用就是在調(diào)用各種中間件;

koa使用co作為底層運(yùn)行框架,使用它完全忘記了什么時(shí)候回調(diào)函數(shù)或者callbackshell;

express歷史更久,裝機(jī)量大,文檔完整,第三方的中間件也很多;

我選擇了express作為node開(kāi)發(fā)框架。

模板引擎

由于之前用node寫過(guò)restFul的網(wǎng)站(詳見(jiàn)我的博客-NodeJS開(kāi)發(fā)個(gè)人博客網(wǎng)站),比較熟悉jade,所以這次直接選擇了pug作為服務(wù)器端模板引擎。
pug是一個(gè)比較靈活的服務(wù)器端模板,express配置起來(lái)也很簡(jiǎn)單,在根目錄的app.js文件中配置

// 設(shè)置模板引擎的類型
app.set("view engine", "pug");
// 設(shè)置模板文件路徑
app.set("views", path.resolve(__dirname, "src/Views"));

這樣,在express渲染時(shí)候使用 res.render("Home/index", {}),指定對(duì)應(yīng)的頁(yè)面模板路徑就行了,第二個(gè)參數(shù) 是要在pug頁(yè)面使用的數(shù)據(jù)內(nèi)容,json格式。

中間層與后端的異步通信

其實(shí)就是個(gè)ajax庫(kù),所以我選擇了axios,vue2官方推薦的ajax庫(kù),內(nèi)置的axios.all(),可以在中間層代理多個(gè)后端請(qǐng)求一并返回,輕松實(shí)現(xiàn)Bigpipe。

模塊化

因?yàn)槭蔷W(wǎng)站前臺(tái)頁(yè)面,需要考慮SEO,無(wú)法使用前端框架,所以換個(gè)思路,使用webpack+es6/AMD來(lái)實(shí)現(xiàn)模塊化。
于是,使用webpack作為打包機(jī)+View層的模塊化,從前端層面實(shí)現(xiàn)了模塊化和組件化。
es6用在Contorl層的模塊化,在node中間層實(shí)現(xiàn)了模塊化

環(huán)境配置(啟動(dòng)文件)

app.js作為項(xiàng)目的啟動(dòng)文件,是express的配置文件,同時(shí)也是運(yùn)行開(kāi)發(fā)環(huán)境 / 生產(chǎn)環(huán)境的配置文件。

通過(guò)node啟動(dòng)時(shí)配置的命令參數(shù),由app.js接收參數(shù),然后運(yùn)行對(duì)應(yīng)的環(huán)境

我們需要安裝cross-env這個(gè)插件

npm i --save-dev cross-env

在package.json的scripts中配置:

...
"scripts": {
    "start": "cross-env NODE_ENV=production node app.js",
    "dev": "cross-env NODE_ENV=dev supervisor -w app.js app",
    "build": "webpack --config build/webpack.prod.config.js"
  }
...

這樣,使用 process.env.NODE_ENV 就可以獲取node啟動(dòng)的環(huán)境參數(shù)。

這里我配置了 開(kāi)發(fā)環(huán)境(dev) 和 生產(chǎn)環(huán)境(production)

開(kāi)發(fā)環(huán)境: 不壓縮代碼,開(kāi)啟devtool生成source-map,便于調(diào)試代碼;

生產(chǎn)環(huán)境: 是用webpack進(jìn)行打包、壓縮、混淆操作,將最終完整的代碼(應(yīng)用)輸出至dist目錄中,然后再啟動(dòng)node服務(wù)器,運(yùn)行應(yīng)用;

上述代碼中還用到了 supervisor插件,這是監(jiān)聽(tīng)node配置文件(app.js)的更改,并自動(dòng)重啟node的。

npm i --save-dev supervisor

前端層面使用webpack-dev-middleware和webpack-hot-middleware,實(shí)現(xiàn)了熱加載。

這樣,從中間層到前端都實(shí)現(xiàn)了熱加載。

node中間層配置

在根目錄下新建了config文件夾,將一些常用的配置/參數(shù)、方法抽出來(lái),寫在了config/config.js 和 config/common.js中。

例如,中間層啟動(dòng)的端口號(hào)、應(yīng)用的根目錄(path.resolve(__dirname,"../"))、后端服務(wù)器的ip、前端SEO的description和keywords等參數(shù),都放在了config.js中,通過(guò)AMD規(guī)范在所有使用的文件中統(tǒng)一引入,修改起來(lái)也方便。

app.js

var express = require("express");
var cookieParser = require("cookie-parser");
var path = require("path");
var localOptions = require("./build/localOptions");
var config = require("./config/config");
var bodyParser = require("body-parser");
var auth = require("./middleware/auth");
var log4js = require("./config/log4js");

process.env.NODE_ENV = process.env.NODE_ENV ? process.env.NODE_ENV : "production";
var isDev = process.env.NODE_ENV === "dev";
var app = express();
var port = config.port;


app.set("view engine", "pug");
// 設(shè)置模板文件路徑
if (isDev){
    app.set("views", path.resolve(__dirname, "src/Views"));
}else {
    app.set("views", path.resolve(__dirname, "dist/Views"));
}

// app.locals定義的鍵值對(duì)能在模板中直接訪問(wèn)
app.locals.env = process.env.NODE_ENV || "dev";
app.locals.reload = true;

app.use(cookieParser());
app.use(bodyParser.urlencoded({extended: false}));


if (isDev) {
    // app.locals.pretty = true;
    // 開(kāi)發(fā)環(huán)境,靜態(tài)文件使用熱插拔
    var webpack = require("webpack");
    var webpackDevMiddleware = require("webpack-dev-middleware");
    var webpackHotMiddleware = require("webpack-hot-middleware");
    var webpackDevConfig = require("./build/webpack.dev.config.js");

    var compiler = webpack(webpackDevConfig);
    // 熱插拔
    app.use(webpackDevMiddleware(compiler, {
        publicPath: webpackDevConfig.output.publicPath,
        noInfo: true,
        stats: "errors-only"
    }))
    app.use(webpackHotMiddleware(compiler, {
        heartbeat: 1000,
        noInfo: true,
    }));

    // 不能熱插拔的往下執(zhí)行
    var reload = require("reload");
    var http = require("http");
    var server = http.createServer(app);
    // reload(server, app);
    reload(app);
    server.listen(port, () => {
        console.log("App【dev】 is now running on port " + port + "!");
    });

    // 靜態(tài)目錄設(shè)置必須有,開(kāi)發(fā)環(huán)境讀取的vendor.js不是內(nèi)存文件;
    // 靜態(tài)目錄設(shè)置必須放在reload后面,避免頁(yè)面引入reload.js報(bào)錯(cuò)
    app.use(express.static(path.join(config.root, "src")));
    app.use("/", require(path.join(config.configRoot,"/routes")));
    
}else {
    // 線上環(huán)境不需要監(jiān)聽(tīng),只需開(kāi)啟node服務(wù)即可
    // 設(shè)置node的靜態(tài)文件目錄
    app.use(express.static(path.join(config.root, "dist")));
    app.use("/",require(path.join(config.configRoot,"/routes")));
    // app.listen(process.env.PORT, () => {
    app.listen(port, () => {
        console.log("App【production】 is now running on port " + port + "!");
    })
}

// 捕捉 404錯(cuò)誤 傳給 error路由
app.use("*", auth, (req, res, next) => {
    let err = new Error("Not Found");
    err.status = 404;
    next(err);
});

// 捕獲 error,跳轉(zhuǎn)至error頁(yè)面
app.use((err, req, res, next) => {
    const sc = err.status || 500;
    if(err.status == 405){
        res.redirect(config.cndesignOrigin + "/Home/GuideAuthentication");
        return;
    }
    res.status(sc);
    // 此處需寫入日志
    log4js.error("
 Status: "+ sc + "
 Message: " + err.message + "
 Href: " + localOptions.baseUrl + req.originalUrl + "
 User-agent: " + req.headers["user-agent"]);

    res.render("Error/404", {
        error: err,
        status: sc,
        message: err.message,
        userInfo: req.userInfo_ || { hasLogin: false }
    });
});

注意Error Handle的掛載的順序,一般掛載到app.use()下,且放在最后。

因?yàn)镋rror Handle的參數(shù)為4個(gè),第一個(gè)參數(shù)err可以通過(guò)路由中的next(err)拋出,這樣所有的路由都可以隨時(shí)拋出error,讓Error Handle來(lái)捕獲。

來(lái)看一下目錄結(jié)構(gòu):

App
├─ .babelrc                         // babel的配置
├─ ReadMe                           
├─ app.js                           // 啟動(dòng)文件
├─ build                            // webpack的配置文件
│    ├─ entrys.js                   // webpack打包js和css的入口文件
│    ├─ localOptions.js             // 前端開(kāi)發(fā)者本地配置文件,本地ip等站點(diǎn)配置
│    ├─ postcss.config.js           // postcss的配置文件
│    ├─ webpack.dev.config.js       // 開(kāi)發(fā)環(huán)境的webpack打包配置
│    ├─ webpack.dll.config.js       // webpack.DllReferencePlugin插件的配置文件
│    └─ webpack.prod.config.js      // 生產(chǎn)環(huán)境的webpack打包配置
├─ config                           // Model層文件:包括node服務(wù)器的配置、路由和代理接口
│    ├─ common.js                   // 中間層邏輯處理的公用方法
│    ├─ config.js                   // node服務(wù)器的配置
│    └─ routes                      // 路由和代理接口配置
│           ├─ default.js
│           ├─ designers.js
│           ├─ home.js
│           └─ index.js             // 路由和接口配置的入口文件
├─ package.json
└─ src                              // View層文件
       ├─ Components                // 公用組件
       │    ├─ base
       │    ├─ home
       │    ├─ index
       │    ├─ message
       │    ├─ modals
       │    ├─ page
       ├─ Views                     // 頁(yè)面
       │    ├─ Default
       │    ├─ Error
       │    ├─ Home
       │    ├─ Include
       │    ├─ Messages
       │    └─ Shared
       └─ assets                    // 靜態(tài)文件目錄
              ├─ Jcrop
              ├─ es5-shim-master
              ├─ images
              ├─ jquery-1.10.2.min.js
              ├─ jquery-ui-1.8.24.min.js
              └─ layui

歡迎繼續(xù)關(guān)注本博的更新
Node中間層實(shí)踐(一)——基于NodeJS的全棧式開(kāi)發(fā)
Node中間層實(shí)踐(二)——搭建項(xiàng)目框架
Node中間層實(shí)踐(三)——webpack配置
Node中間層實(shí)踐(四)——模板引擎pug
Node中間層實(shí)踐(五)——express-中間層的邏輯處理

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92710.html

相關(guān)文章

  • 如何打造一個(gè)令人愉悅的前端開(kāi)發(fā)環(huán)境(三)

    摘要:的最后一個(gè)大招就是替換一些傳統(tǒng)的服務(wù)端語(yǔ)言,例如,,等,在業(yè)務(wù)層上面使用來(lái)開(kāi)發(fā)服務(wù)端完全不成問(wèn)題。更多的的使用細(xì)節(jié)和技巧建議關(guān)注美團(tuán)博客大搜車論壇下一篇我們開(kāi)啟如何結(jié)合和搭建一個(gè)開(kāi)發(fā)環(huán)境和項(xiàng)目目錄 往期回顧 前面2期都講得是瀏覽器端的東西比較多,包括Webpack,雖然是Node處理的,但是還是瀏覽器端用的多,對(duì)于現(xiàn)在的前端開(kāi)發(fā)來(lái)說(shuō),不懂一點(diǎn)服務(wù)端的東西,簡(jiǎn)直沒(méi)辦法活,一般的招聘要求都...

    cgh1999520 評(píng)論0 收藏0
  • Node間層實(shí)踐(一)——基于NodeJS的全棧式開(kāi)發(fā)

    摘要:總結(jié)我覺(jué)得,以后基于的全棧式開(kāi)發(fā)的模式將會(huì)越來(lái)越流行,這也會(huì)引領(lǐng)前端步入工程化時(shí)代。歡迎繼續(xù)關(guān)注本博的更新中間層實(shí)踐一基于的全棧式開(kāi)發(fā)中間層實(shí)踐二搭建項(xiàng)目框架中間層實(shí)踐三配置中間層實(shí)踐四模板引擎中間層實(shí)踐五中間層的邏輯處理 版權(quán)聲明:更多文章請(qǐng)?jiān)L問(wèn)我的個(gè)人站Keyon Y,轉(zhuǎn)載請(qǐng)注明出處。 前言 近期公司有個(gè)新項(xiàng)目,由于后端人手不足,我果斷的提議用node中間層的方案,得到了老大的支持...

    warkiz 評(píng)論0 收藏0
  • Node間層實(shí)踐(三)——webpack配置

    摘要:的意思是,如果碰到不能的情況,就整頁(yè)刷新首頁(yè)路由開(kāi)發(fā)環(huán)境中使用了,需要將每一個(gè)的配置中寫上歡迎繼續(xù)關(guān)注本博的更新中間層實(shí)踐一基于的全棧式開(kāi)發(fā)中間層實(shí)踐二搭建項(xiàng)目框架中間層實(shí)踐三配置中間層實(shí)踐四模板引擎中間層實(shí)踐五中間層的邏輯處理 版權(quán)聲明:更多文章請(qǐng)?jiān)L問(wèn)我的個(gè)人站Keyon Y,轉(zhuǎn)載請(qǐng)注明出處。 這里沒(méi)什么可說(shuō)的,webpack的配置和插件實(shí)在太多了,用的時(shí)候查文檔就行了。 項(xiàng)目地...

    kelvinlee 評(píng)論0 收藏0
  • 構(gòu)建前端項(xiàng)目

    摘要:解決思路服務(wù)器端渲染服務(wù)器端和前端公用同一個(gè)應(yīng)用,然后通過(guò)構(gòu)建工具及配置,確定哪些組件需要再服務(wù)器端渲染,那些組件需要再客戶端渲染。服務(wù)器端渲染,由框架與構(gòu)建工具配合,并依據(jù)一定的項(xiàng)目結(jié)構(gòu)和編碼方式,共同運(yùn)行。 分離 為什么需要 前后端分離、web服務(wù)器與static服務(wù)器分離: 前端與后端耦合 (需求) 自動(dòng)化、工程化的構(gòu)建前端的代碼 (基礎(chǔ)條件) 模塊化、組件化,項(xiàng)目共享代碼 (...

    mindwind 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<