如今的 Node 对于前端而言能够涵盖各个方面,包括命令行接口、插件、依赖库、脚手架以及 Web 服务等。本文是一篇对于 Node 使用的浅谈文章,会简单讲解一些我的使用 Node 的经验,分享的内容主要可分为三个方面:javascript
工具篇会讲解使用 NPM 发布命令行接口的简单教程。插件篇主要讲述如何开发一个有趣的 Webpack 插件(Vue CLI / Babel 插件同理)。服务篇会讲解一些基于 Express 应用框架的技术选型方案,这类技术每每对于作一些前端工具平台很是有用(例如 Mock 平台、多语言平台等,每每可配合命令行接口进行设计)。因为篇幅较长,本文只讲解服务篇内容。css
舒适提示:这里的服务篇主要讲解了一些本身搭建 Express 应用的经验,是本身学习 Node 的一个过程。你们若是喜欢折腾或者想作一些前端的工具平台能够按照这种思路去尝试,可是若是要作业务项目,你们仍是要选择一些成熟稳定的技术方案,考虑的方面须要更多。html
基于 Node.js 的 Web 应用框架不少,包括但不限于前端
这里盗一张 2019 Node.js Frameworks star 状况(供你们参考):java
本文主要讲解 Express 应用框架,虽然它提供的能力很是简单,但对于一些工具平台的开发彻底能够胜任,而且能够写出各类千奇百怪的 MVC 模式(若是对服务端 MVC 不是很清晰能够阅读 服务端 MVC 之 Model2 的衍生)。这里简单介绍之前设计的几种基于 Express 扩展的技术选型方案,刚好涵盖了 React、Angular 以及 Vue 这三个 Web 前端框架。node
舒适提示:接下来使用的示例项目都相对简单,但愿对刚入门 Express 的小白们有所启示。react
2016年7月到10月,从零开始学习 React 并使用 React 设计了服务端渲染的 Express 应用(同年10月25日诞生了 Next.js ),大体的技术选型以下:webpack
因为对 React 不是很熟悉,首先实现了单页应用,而后实现了服务端渲染应用。ios
在使用 React 以前只会简单的使用 Bootstrap,当时对 React 的学习历程大体以下:git
学习总结文档以下:
以上学习过程记录在 react-demo 和 react-start-kit (小而全的概念性参考价值)中,此时只是简单的 React 单页应用设计过程。大体结构以下:
舒适提示:在先后端分离的开发模式中,若是 Web 前端实现的是 SPA(单页应用),服务端能够选用不一样的设计语言,例如 Node.js、Java 或者 Golang 等。Web 前端能够经过 Express渲染服务器 进行后端的请求代理转发。若是想要前端先行,可使用 Easy Mock 或者本身设定的 JSON 数据模拟后端提供的接口规范。
服务端的设计选用 Node.js 的 Express 框架,大体实现步骤以下:
以上实现过程记录在一个简单的示例 rewatch 里,入口文件是 app.js
。此时先后端分离,能够同时启动服务端 Express 服务和启动开发态 React 调试页面服务(webpack-dev-server),并使用开发态页面向 Express 服务发送请求获取接口数据(当时使用 JQuery 的$.ajax
发送请求)。设计完成后将开发态页面使用 Webpack 打包构建,构建目录为服务端 Express 的静态资源目录。首屏渲染的工做交给 Ejs 模板引擎(事实上也能够直接使用 HTML 字符串渲染)进行处理。大体结构以下:
单页应用在路由跳转时不须要额外的请求静态资源,能够提高用户的体验。可是若是应用较大,首次请求静态资源和进行页面动态渲染的过程当中会产生如下问题:
为了解决上述客户端的渲染问题,须要实现 React 服务端渲染。因为当时还没出现成熟的服务端渲染应用框架,所以只能本身摸索构建 React 服务端渲染方案:
react-redux
数据 store
的统一(这个印象深入,当时思索了好久)使用了服务端渲染方案后,能够去除以前的 Ejs 模板引擎,当时设计的大体结构以下:
当页面发送路由请求时,Express 服务端使用 react-router
匹配相应路由对应的 React 组件实例并调用 renderToString
方法进行服务端页面渲染(实现页面的局部刷新)。当页面渲染完成后,由 React 打包后的静态资源对页面进行 hydrate 处理。此时的 React 代码是同构的,所以须要注意哪些会运行在服务端,哪些会运行在客户端。同时服务端须要对同构代码进行Webpack 打包处理。
以上实现记录在示例 rewatch 中,入口文件是 server.js
,因为文件比较混乱(把客户端渲染和服务端渲染的示例放在了同一个文件项目中),这里给出另一个很是简单的示例 rewatch-server-render,项目目录结构以下:
.
├── public # 静态资源目录
│ └── js
│ ├── bundle.js # react 目录打包文件
│ ├── common.js # react 目录打包公共文件
│ ├── react-dom.min.js # react 库文件
│ └── react.min.js # react 库文件
├── react # react 同构代码目录(没有 react-router,能够查看 rewatch 示例)
│ ├── actions
│ ├── components
│ ├── containers
│ ├── reducers
│ ├── store
│ └── index.js
├── server # 服务端
│ └── routes # 服务端路由(没有使用 react-router 同构,能够查看 rewatch 示例)
├── server.js # 开发态服务入口文件
├── server.bundle.js # 生产态服务入口文件
├── webpack.browser.config.js # 静态资源打包的 webpack 配置(目标文件 bundle.js、common.js)
└── webpack.node.config.js # 服务端打包的 webpack 配置(目标文件 server.bundle.js)
复制代码
2016年10月到2017年3月,使用 Angular 设计了一个 Express 应用,大体的技术选型以下:
这是一个简单的服务端多页应用示例,使用 Ejs 模板引擎进行页面渲染,渲染完成后交由 Anguar 进行页面的响应操做(发送请求使用 Angular 内置的 $http
服务)。该示例不须要额外的 Webpack 配置,只须要启动 Express 服务自己渲染设计便可。目录结构以下:
.
├── client # 静态资源目录
│ ├── css/ # 样式
│ ├── imgs/ # 图片
│ ├── js/ # 脚本
│ │ ├── angular/ # angular应用
│ │ │ ├── controllers/ # angular控制器
│ │ │ ├── services/ # angular服务
│ │ │ └── webapp.js/ # angular自动引导应用程序
│ │ └── sockets/ # sockets应用
│ └── lib # 插件(包括angualr、bootstrap/bootstrap-table、chart等)
├── config # 配置(包括Redis、Mongoose配置)
│ ├── config.js # 参数配置
│ └── index.config.js # 导出配置
├── server # 服务端
│ ├── constants/ # 常量
│ ├── controllers/ # 控制器
│ ├── events/ # 事件
│ ├── models/ # 模型
│ ├── routes/ # 路由
│ ├── sockets/ # socket.io
│ ├── pubs/ # Redis发布
│ └── subs/ # Redis订阅
├── views # 视图(使用Ejs模板引擎)
└── app.js # 服务入口文件
复制代码
舒适提示:这种多页应用框架是自然的 SSR 模型,通常都须要配合模板引擎进行设计。
2018年6月,使用 Vue 设计了服务端渲染的 Express 应用,大体技术选型以下:
该技术选型最主要的特色以下:
在 Nuxt 的目录结构中,服务端引入的同构代码放在.nuxt
目录中,是 Webpack 打包后的代码文件,所以若是服务端不使用特殊的语法,彻底不须要 Backpack 配置。此项目为了支持服务端 TypeScript 语法,使用 Backpack 对服务端代码进行构建(不影响同构部分代码的构建,同构代码在 Nuxt 里是经过读取文件的方式获取)。
.
├── .nuxt # Nuxt构建目录(Nuxt预设目录)
├── assets # 资源目录(Nuxt预设目录)
│ ├── img # 图片
│ ├── icon # 图标
│ └── style # 样式
├── build # 配置(包括Redis、Mongoose配置)
│ └── main.js # 服务端Backpack构建的目标启动入口文件
├── common # 先后端通用
│ ├── constants/ # 常量
│ └── types/ # TypeScript接口
├── components # 组件目录(Nuxt预设目录)
├── constants # 前端常量目录
├── docs # 文档目录(渲染.md文件)
├── graphql # 前端Graphql请求接口
├── layouts # 布局目录(Nuxt预设目录)
├── middleware # 中间件目录(Nuxt预设目录)
├── mixins # 全局mixins
├── modules # Nuxt模块(TypeScrpt的Webpack配置扩展)
├── pages # 页面目录(Nuxt预设目录)
├── plugins # 插件目录(Nuxt预设目录)
├── server # 服务端目录
│ ├── constants/ # 常量
│ ├── database/ # 数据库模型
│ ├── express/ # 服务对外的公共API接口
│ │ ├── controllers/ # 控制器
│ │ ├── routes/ # 路由
│ │ └── services/ # 服务
│ ├── graphql/ # 服务内部的Graphql查询接口
│ │ ├── middlewares/ # Graphql中间件
│ │ ├── resolvers/ # Graphql Resolver
│ │ ├── schemas/ # Graphql Schema
│ │ └── index.ts # graphql接口入口文件
│ ├── types/ # TypeScript接口
│ ├── utils/ # 工具方法
│ └── index.ts # 服务端入口文件(Backpack构建入口地址)
├── static # 静态文件目录(Nuxt预设目录)
├── store # Vuex目录(Nuxt预设目录)
├── utils # 客户端工具方法
├── .cz-config.js # cz提交配置文件
├── .env # 环境变量
├── .gitignore # Git忽视文件
├── .huskyrc # Git钩子配置文件
├── .vcmrc # cz校验配置
├── app.html # html文件
├── backpack.config.js # Backpack配置文件
├── CHANGELOG.md # 升级日志
├── ecosystem.config.js # PM2启动配置文件
├── index.d.ts # TypeScript声明文件
├── nuxt.config.js # Nuxt配置文件
├── package.json # 项目描述文件
├── README.md # 说明
├── tag.bat # 项目打Tag脚本
└── tsconfig_node.json # TypeScript配置文件
复制代码
在package.json
中的配置脚本以下:
"build": "cross-env NODE_ENV=production nuxt build && backpack build",
"pm2": "pm2 start ecosystem.config.js",
"pm2:stop": "pm2 stop ecosystem.config.js",
"dev:client": "cross-env NODE_ENV=development DEV_TYPE=nuxt ts-node --compiler ntypescript --project tsconfig_node.json ./server",
"dev:server": "cross-env NODE_ENV=development DEV_TYPE=server ts-node-dev --compiler ntypescript --project tsconfig_node.json ./server"
复制代码
build
:使用 Webpack 构建 Nuxt 资源包以及使用 Backpack 构建服务端入口文件(转义 TypeScript)pm2
:以生产模式启动一个进程守护的 Web 服务器pm2:stop
:中止运行 Web 服务器dev:client
:启动开发态热部署前端渲染服务dev:server
:启动开发态热启动服务端服务虽然是服务端渲染框架(理论上能够一我的开发项目,启动一个热加载的服务端命令便可),可是在开发的过程当中考虑到多人协做以及开发的便利性仍然将客户端和服务端进行分离。
在服务端配置 Nuxt 的 Builder
会致使服务端热加载过慢,所以将服务端 Nuxt 的 Builder
过滤掉,使用 ts-node-dev 作服务端热启动。在客户端使用 ts-node 启动服务,经过识别 DEV_TYPE
环境变量加载Nuxt的 Builder
,实现 Web 前端的热加载功能。须要注意客户端向服务端发送请求是跨域的,所以在服务端的开发态环境须要配置容许跨域。
舒适提示:一个服务端渲染框架楞是让我拆成了先后端开发分离的框架模式。
设计了以上三个方案后,发现从零开始构建一个 Express 应用时至少须要考虑如下几个方面:
$.ajax
对于 Express 新手而言,能够先尝试多页应用 + MongoDB + 模板引擎 + JQuery 的选型方案:
若是前端框架选型是 React 或 Vue(一般是单页应用设计),而且须要使用 ES6 / ES7 / JSX 以及 Vue 的 SFC 格式等语法,那么Web前端势必要设计 Webpack 的构建配置,此时可使用相似于 webpack-dev-server
的 Express 开发态渲染服务器设计和调试开发态前端页面。固然目前的 Web 前端开发针对不一样的前端框架都有本身设计的脚手架,所以能够直接使用脚手架进行开发设计和静态资源构建。同时若是框架中没有内置 HTTP 请求库,能够本身封装或者使用一些成熟的 HTTP 库,例如axios、request以及superagent等。若是须要使用 UI 组件库进行页面设计,能够根据使用的框架进行 UI 组件库选型,例如 React 的 Ant Design、Vue 的 Element 等。Express 服务端的设计因为使用了主流框架的动态渲染能力,所以能够去除模板引擎渲染功能。若是想支持 Node.js 不支持的 ES6 / ES7 / TypeScript 语法等,那么须要 Backpack 进行服务端构建。
舒适提示:主流框架的应用设计和简单的起手式不一样,先后端开发能够彻底分离,这样的应用设计大大解放了前端的生产力(前端再也不受限于服务端的模板引擎)。例如目前的主流框架设计的一些脚手架,能够优雅的将 Webpack 配置,开发态渲染服务器以及请求代理结合在一块儿,作到开箱即用,提高用户的开发体验。
Hi,你们好,咱们是阿里巴巴新成立的 BU 政务钉钉事业部(杭州同窗在用的健康码是我 BU 联合其余 BU 共同设计的一个项目),目前还有大量的 Web 前端职位空缺。但愿想找我内推或者想了解更多招聘信息的同窗能够加我微信:18768107826