静态网页与动态网页
静态页面:
- 客户/消费者的观点:一个 url 指向同一个 html 文件
- 服务器/生产者的观点:存储在 Web 服务器根文件夹内或子文件夹内的文件
- HTML 文件:无论何时当一个特定资源被请求的时候都返回相同的被硬编码的内容
- 可以直接在浏览器上显示
动态页面:
- 客户/消费者的观点:url 指的是动态 html(可能每次请求都不同)
- 服务器/生产者的观点:程序/脚本生成 html
- 它不是一个 html,而是一个程序产生的 html(s),页面通常是通过将数据库的数据植入到 HTML 模板中的占位符中而产生的。
- 不能直接在浏览器中显示
服务端编程
服务器端页面是使用多种 web 编程语言/框架之一编写的程序
例如:PHP,Java/JSP,Ruby on Rails,ASP.NET, Python, Perl
每种语言/框架都有其优点和缺点
服务端编程的优势
- 信息的高效存储和传输
- 定制用户体验
- 控制对内容的访问
- 存储会话和状态信息
- 通知和通讯
- 数据分析
Node.js
Node(正式名称 Node.js)是一个开源的、跨平台的运行时环境
服务端 Javascript:开发人员可以使用 JavaScript 创建各种服务器端工具和应用程序
事件驱动,异步 I/O 框架
性能:在 v8 之上的 c ++内核
在单一进程中可以最小的开销(cpu/内存)处理成千上万的并发连接
模块系统
不是一个 web 框架,也不是一种语言
Node.js is a platform built on Chrome's JavaScript runtime for easily building fast,scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.
——from nodejs.org
Node.js 的诞生
Ryan Dahl 于 2009 年创造
由 Joyent(一家位于硅谷的创业公司)开发和维护,注册了“Node.js”这个商标,使用其相关内容需要得到法律授权。
- 2014,开源社区 io.js
- 2015,Node.js 基金会,支持社区驱动的开放管理模式 2019,
- Node.js 基金会与 JS 基金会合并,成立 OpenJS 基金会
- Licence MIT
Node.js 现状
2018 年 5 月 31 日,Node.js 基金会发布的用户调查报告,显示学习 Node.js 看起来更容易了,少于 2 年 node 经验的用户中,有 43% 的觉得“容易”。绝大多数(85%)Node.js 用户用于网页开发,43% 参与一些企业级开发,13% 用于大数据分析,8% 用于嵌入式系统。
Node.js 应用场景
- 网站(如 express/koa 等)
- im 即时聊天(socket.io)
- api(移动端,pc,h5)
- HTTP Proxy(淘宝、Qunar、腾讯、百度都有)
- 前端构建工具(grunt/gulp/bower/webpack/fis3……)
- 写操作系统(NodeOS)
- 跨平台打包工具(PC 端的 electron、nw.js,比如钉钉 PC 客户端、微信小程序 IDE、微信客户端,移动的 cordova,即老的 Phonegap,还有更加有名的一站式开发框架 ionicframework)
- 命令行工具(比如 cordova、shell.js)
- 反向代理(比如 anyproxy, node-http-proxy)
Node 优势
从 web 服务器开发的角度来看,Node 有很多好处:
- 卓越的性能表现!Node 为优化 web 应用的吞吐量和扩展度而生,对常见的 web 开发问题是一套绝佳方案(比如实时 web 应用)。
- 代码还是熟悉的老伙伴 JavaScript,这意味着在客户端和服务器端“上下文切换”的时间成本更低。
- 与传统的 web 服务器语言(例如 Python、PHP 等)相比,JavaScript 理念更新,语言设计的改进带来了诸多好处。许多其它新近流行的语言也可编译/转换成 JavaScript,所以 TypeScript、CoffeeScript、ClojureScript、Scala、LiveScript 等等也可以使用。
- Node 包管理工具(node package manager,NPM)提供了数十万个可重用的工具包。它还提供了一流的依赖解决方案,可实现自动化工具链构建。
- Node.js 是可移植的,可运行于 Microsoft Windows、macOS、Linux、 Solaris、FreeBSD、OpenBSD、WebOS 和 NonStop OS。此外,许多 web 主机供应商对其提供了良好支持(包括专用的基础框架和构建 Node 站点的文档)。
- 它有一个非常活跃的第三方生态系统和开发者社区,很多人愿意提供帮助。
何时使用
Node 所针对的应用程序有一个专门的简称:DIRT,表示数据密集型实时(data-intensive real-time)程序。
性能和 I/O 负载:Nodejs 非常好的解决了 IO 密集的问题,通过异步 IO 来实现。
大前端的基石。
从脚手架、辅助前端开发(比如 SSR、PWA 等)的快速开发实践,到 API 中间层、代理层,到专业的后端开发都有非常成熟的经验。
全栈。
PWA(Progressive Web Apps,渐进式 Web 应用)运用现代的 Web API 以及传统的渐进式增强策略来创建跨平台 Web 应用程序。这些应用无处不在、功能丰富,使其具有与原生应用相同的用户体验优势
Node.js 不适合的领域
计算密集型应用内存控制
大内存的应用,由于 V8 引擎有内存设计的限制,32 位环境中最大堆是 1G,64 位环境中最大堆也不到 2G,如果要一次读入 10G 数据,对于 Nodejs 来说也无法实现。
静态服务器,虽然 Nodejs 的优势在 IO 密集集应用,但是和 Nginx 的处理静态资源还是有很大的差距。
不需要异步的应用:比如系统管理,自行化脚本等,Nodejs 的异步调用可能会给编程带来一些麻烦。
Node.js 事件循环
事件驱动模型
由一个事件收集器、一个事件发送器和一个事件处理器组成。
Node.js 支持 JavaScript
这是 Node.js 能够发展壮大的一个非常重要的间接原因。
- 首先,Javascript 作为前端工程师的主力语言,在技术社区中有相当的号召力。而且,随着 Web 技术的不断发展,特别是前端的重要性增加,不少前端工程师开始试水”后台应用“,在许多采用 Node.js 的企业中,工程师都表示因为习惯了 Javascript,所以选择 Node.js。
- 其次,Javascript 的匿名函数和闭包特性非常适合事件驱动、异步编程。
- 有 Google V8 引擎的加持,Node.js 的性能也是受益其中。
同步 vs 异步
同步 | 异步 |
---|---|
等待每个操作完成,然后执行下一个操作。 | 从不等待每个操作完成,一次执行所有操作。 |
一步一步执行 | 回调,用于处理结果 |
同步式 I/O 和异步式 I/O 的特点
阻塞方法同步执行,非阻塞方法异步执行。
同步式 I/O(阻塞式) | 异步式 I/O(非阻塞式) |
---|---|
利用多线程提供吞吐量 | 单线程即可实现高吞吐量 |
通过时间片分割和线程调度利用多核 CPU | 通过功能划分利用多核 CPU |
需要由操作系统调度多线程使用多核 CPU | 可以将单进程绑定到单核 CPU |
难以充分利用 CPU 资源 | 可以充分利用 CPU 资源 |
内存轨迹大,数据局部性弱 | 内存轨迹小,数据局部性强 |
符合线性的编程思维 | 不符合线性的编程思维 |
阻塞 vs 非阻塞
阻塞是指在 Node.js 程序中,其它 JavaScript 语句的执行, 必须等待一个非 JavaScript 操作完成。这是因为当阻塞发生时,事件循环无法继续运行 JavaScript。
在 Node.js 中,JavaScript 由于执行 CPU 密集型操作,而不是等待一个非 JavaScript 操作(例如 I/O)而表现不佳,通常不被称为阻塞。在 Node.js 标准库中使用 libuv 的同步方法是最常用的阻塞操作。原生模块中也有阻塞方法。
在 Node.js 标准库中的所有 I/O 方法都提供异步版本,非阻塞,并且接受回调函数。某些方法也有对应的阻塞版本,名字以 Sync 结尾。
示例:从文件中读取数据并显示数据
阻塞
同步文件读取
- 从文件读取数据
- 显示数据
- 完成其他任务
1 |
|
非阻塞
异步:
- 从文件中读取数据。当读取数据完成时,显示数据
- 完成其他任务
1 |
|
开始
https://nodejs.org/en/download/
Node Package Manager (NPM)
- <www.npmjs.org>
- 1450.000+modules
- package.json 文件(npm init)
npm install <module.name> --save
文件 package.json
项目信息:
- name 项目名称
- version 项目的版本号
- description 项目的描述信息
- entry point 项目的入口文件
- test command 项目启动时脚本命令
- git repository 如果你有 Git 地址,可以将这个项目放到你的 Git 仓库里
- keywords 关键词
- author 作者叫啥
- license 项目要发行的时候需要的证书,平时玩玩忽略它
安装模块
1 |
|
NodeJS API
Node.js 流行模块
Express.js 由核心 Node 项目团队的成员之一 TJ Holowaychuk 构建。大型社区支持此框架,因此具有不断更新和改革所有核心功能的优势。这是一个极简主义的框架,用于构建 mobile 应用程序和 API。
Koa 由创建 Express.js 的同一团队开发,通常被称为下一代 NodeJS 框架。Koa 的独特之处在于它使用了一些非常酷的 ECMAScript(ES6)方法,使你无需回调即可工作,同时极大地扩展了错误处理。
Hapi 是一个强大且健壮的框架,用于开发 API。完善的插件系统和各种关键功能(例如输入验证、基于配置的功能、实现缓存、错误处理、日志记录等)使 Hapi 成为最受欢迎的框架之一。它用于构建有用的应用,并通为 PayPal,Disney 等多个大型网站提供技术解决方案。Hapi 以最小的开销构建安全、强大、可扩展的开箱即用的功能。
Socket.io 用于构建实时 Web 应用。这是一个 Javascript 库,可在 Web 客户端和服务器之间进行双向数据通信。异步数据 I/O、二进制流和即时消息传递是此框架最重要的功能。
Meteor.JS 是最常用的 NodeJS 框架之一。NodeJS 的全栈框架,允许用户构建实时应用程序。它用于创建基于移动和基于 Web 的 javascript 应用。
模块
两种模块,不兼容
- ES6 模块,简称 ESM
- Node.js 专用的 CommonJS 模块,简称 CJS
ES6 模块与 CommonJS 模块的差异
语法
CommonJS 模块使用 require() 加载和 module.exports 输出
ES6 模块使用 import 和 export
1 |
|
1 |
|
- CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
- CommonJS 加载的是一个对象(即 module.exports 属性),该对象只有在脚本运行完才会生成。
- ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
模块加载的实质
1 |
|
ES6
1 |
|
Node.js 的区分
Node.js 要求 ES6 模块采用.mjs 后缀文件名。
- 只要脚本文件里面使用 import 或者 export 命令,那么就必须采用.mjs 后缀名。Node.js 遇到.mjs 文件,就认为是 ES6 模块,默认启用严格模式,不必在每个模块文件顶部指定"use strict"。
- 如果不希望将后缀名改成.mjs,可以在项目的 package.json 文件中,指定 type 字段为 module。
.cjs 文件总是以 CommonJS 模块加载。如果没有 type 字段,或者 type 字段为 commonjs,则.js 脚本会被解释成 CommonJS 模块。
.js 文件的加载取决于 package.json 里面 type 字段的设置。
注意,ES6 模块与 CommonJS 模块尽量不要混用!!!
require 命令不能加载.mjs 文件,会报错,只有 import 命令才可以加载.mjs 文件。反之,.mjs 文件里面也不能使用 require 命令,必须使用 import。
同时支持两种格式的模块
如果原始模块是 ES6 格式,那么需要给出一个整体输出接口,比如 export dlefault obj,使得 CommonJS 可以用 import() 进行加载。
如果原始模块是 CommonJS 格式,那么可以加一个包装层。
1 |
|
可以把这个文件的后缀名改为.mjs,或者放在一个子目录,再在这个子目录里面放一个单独的 package.json 文件,指明 {type:"module"}。
另一种做法是在 package.json 文件的 exports 字段,指明两种格式模块各自的加载入口。
1 |
|
require 方法查找策略
A simple file server
1 |
|
1 |
|
as
1 |
|
export default
1 |
|
循环加载
1 |
|
1 |
|
1 |
|
1 |
|
ES6 循环加载-1
1 |
|
1 |
|
1 |
|
ES6 循环加载-2
1 |
|
1 |
|
1 |
|
Node.js 版本
版本帝
LTS 和 Current 其实并不是版本,而是同一个主版本号的不同阶段
LTS:Long Term Support。该版本进入了漫长的维护期。它又分为两个阶段:Active LTS 和 Maintenance LTS。从以往的发布历史看,LTS 至少会被跟进 2 年时间,按照最新的官方网站的说法,Active LTS 持续 12 个月,Maintenance LTS 将会被持续维护 18 个月的时间。Nodejs 12 之前,active 阶段持续 18 个月,maintenance 阶段持续 12 个月。
Current:一个新主版本号 release 后,先进入 Current 阶段,该阶段持续 6 个月,目的是给各个库(library)的作者时间来支持新版。偶数版本在 Current 阶段后进入 LTS 阶段,而奇数版本则终结不再维护
奇偶版本号
- Nodejs 主版本号(semver—major)奇数版本和偶数版本有不同的生命周期。
- 每隔 6 个月,社区会从 Nodejs master 分支拉出一个分支作为主版本的 release。偶数版本在 4 月发版,奇数版本则在 10 月。
- 奇数版本发版时,上一个偶数版本会进入 LTS 阶段,而奇数版本则只持续 6 个月的时间,则终结不再维护。
已无性能优势?
- 实现成本
- 调优成本
- 学习成本
MEAN
MEAN 是一个 Javascript 平台的现代 Web 开发框架总称
- MongoDB 是一个使用 JSON 风格存储的数据库,非常适合 javascript。(JSON 是 JS 数据格式)
- ExpressJS 是一个 Web 应用框架,提供有帮助的组件和模块帮助建立一个网站应用。
- AngularJS 是一个前端 MVC 框架。
- Node.js 是一个并发异步事件驱动的 Javascript 服务器后端开发平台。
MEAN 架构原理
Web 框架
框架名称 | 特性 | 点评 |
---|---|---|
Express | 简单、实用,路由中间件等五脏俱全 | 最著名的 Web 框架 |
Derby.js && Meteor | 同构 | 前后端都放到一起,模糊了开发便捷,看上去更简单,实际上对开发来说要求更高 |
Sails、Total | 面向其他语言,Ruby、PHP 等 | 借鉴业界优秀实现,也是 Node.js 成熟的一个标志 |
MEAN.js | 面向架构 | 类似于脚手架,又期望同构,结果只是蹭了热点 |
Hapi 和 Restfy | 面向 Api&& 微服务 | 移动互联网时代 Api 的作用被放大,故而独立分类。尤其是对于微服务开发更是利器 |
ThinkJS | 面向新特性 | 借鉴 ThinkPHP,并慢慢走出自己的一条路,对于 Async 函数等新特性支持,无出其右 |
Koa | 专注于异步流程改进 | 下一代 Web 框架 |
Node.JS 框架的优势
现在 NodeJS 框架正在成为最常用的构建 Web 应用前后端的开发框架。这是自定义 Web 开发的首选环境。让我们检查一些主要的 NodeJS 框架的优点:
- 实时工作环境
- 简单的编码经验
- 无缝数据流
- 在整个开发过程中使用相同的代码模式
- 方便易用
框架选型
业务场景、特点
自身团队能力、喜好,有时候技术选型决定团队氛围的,需要平衡激进与稳定
熟悉程度
个人学习求新,企业架构求稳,无非喜好与场景而已
预处理器
名称 | 实现 | 描述 |
---|---|---|
模板引擎 | art... | 上百种之多,自定义默认,编译成 html,继而完成更多操作 |
css 预处理器 | less | 自定义语法规则,编译成 css |
js 友好语言 | coffeescript、typescript | 自定义语法规则、编译成 js |
跨平台
平台 | 实现 | 点评 |
---|---|---|
Web/H5 | 纯前端 | |
PC 客户端 | nw.js 和 electron | 尤其是 atom 和 vscode 编辑器最为著名,像钉钉 PC 端,微信客户端、微信小程序 IDE 等都是这样的,通过 web 技术来打包成 PC 客户端 |
移动端 | cordova(旧称 PhoneGap),基于 cordova 的 ionicframework | 这种采用 h5 开发,打包成 ipa 或 apk 的应用,称为 Hybrid 开发(混搭),通过 webview 实现所谓的跨平台,应用的还是非常广泛的 |
其他
用途 | 说明 | 前景 |
---|---|---|
爬虫 | 抢了不少 Python 的份额,整体来说简单,实用 | 看涨 |
命令行工具 | 写工具、提高效率,node+npm | 看涨 |
微服务与 RPC | Node 做纯后端不好做,但在新项目和微服务架构下,必有一席之地 | 看涨 |
微信公众号开发 | 已经火了 2 年多了,尤其是付费阅读领域,还会继续火下去,gitchat 就是使用 Node.js 做的 | 看涨 |
反向代理 | Node.js 可以作为 nginx 这样的反向代理,比如 node-http-proxy 和 anyproxy 等,其实使用 Node.js 做这种请求转发是非常简单的 | 看涨 |