Frontend Engineering

持续更新

项目构建

vue cli

npm install -g @vue/cli
npm install vue@next

vue create project-name

vite

npm create vite@latest
//or
yarn create vite
//or
pnpm create vite

包管理

版本号:x.x.x

  • 主版本号: 当API发生改变,并与之前的版本不兼容的时候
  • 次版本号: 当增加了功能,但是向后兼容的时候
  • 补丁版本号: 当做了向后兼容的缺陷修复的时候

npm

Node Package Manager

dependencies(生产环境)和 devDependencies(开发环境),前者是项目运行时所需要的包,后者是开发时需要的包例如打包项目的 webpack

npm install --save-dev packageName
# 开发环境简写
npm i -D packageName

npm install --save packageName
# 生产环境简写,也可以不带S
npm i -S packageName
  • devDependencies 里面的依赖只用于开发环境,不用于生产环境。而 dependencies 依赖的包不仅开发环境能使用,生产环境也能使用。
  • 两种环境的的指定方式是通过配置文件中的NODE_ENV=developementNODE_ENV=production来指定是开发还是生产环境的。
  • 使用的一些构建工具例如glup、webpack这些只是在开发中使用的包,上线以后就和他们没关系了,所以将它写入devDependencies

install的tag

标签可以用来提供一个别名,而不是版本号。

例如,一个项目可能会选择有多个开发流,并为每个开发流使用不同的标签,例如,stable、beta、dev、canary。

默认情况下,latest 标签被npm用来识别软件包的当前版本,npm install (没有任何@或@指定符)会安装 latest 标签。通常情况下,项目只对稳定的发布版本使用 latest 标签,而对不稳定的版本(如预发布)使用其他标签。

下一个标签被一些项目用来标识即将发布的版本。

除了 latest ,没有任何标签对npm本身有任何特殊意义。

next标签:包如果还不够稳定,但是又想给别人测试使用,可以给这种即将上线的包的版本打上next标签。

install 的 package

A package is:

  • a) a folder containing a program described by a package.json file
  • b) a gzipped tarball containing (a)
  • c) a url that resolves to (b)
  • d) a <name>@<version> that is published on the registry (see registry) with (c)
  • e) a <name>@<tag> (see npm dist-tag) that points to (d)
  • f) a <name> that has a “latest” tag satisfying (e)
  • g) a <git remote url> that resolves to (a)

init package信息:

  • “name”:全部小写,没有空格,可以使用下划线或者横线
  • “version”: x.x.x 的格式,符合 “语义化版本规则”
  • description:描述信息,有助于搜索
  • main:入口文件,一般都是 index.js
  • scripts:支持的脚本,默认是一个空的 test
  • keywords:关键字,有助于在人们使用 npm search搜索时发现你的项目author :作者信息
  • license :默认是 MIT
  • bugs:当前项目的一些错误信息,如果有的话

npm run xxx到底干了什么

  1. 运行 npm run xxx的时候,npm 会先在当前目录的 node_modules/.bin 查找要执行的程序,如果找到则运行;
  2. 没有找到则从全局的 node_modules/.bin 中查找,npm i -g xxx就是安装到到全局目录;
  3. 如果全局目录还是没找到,那么就从 path 环境变量中查找有没有其他同名的可执行程序。

常用命令

  • npm shrinkwrap

    repurposes package-lock.json into a publishable npm-shrinkwrap.json or simply creates a new one; is unaware of workspaces.

    • when run npm install: npm-shrinkwrap.json>package-lock.json>yarn.lock

npx

一个 CLI 工具,其目的是使安装和管理托管在 npm 注册表中的依赖关系变得容易。

能够更方便地安装和运行二进制包,并且还能远程运行 **gist(**Github的一个子服务. 最简单的功能就是分享代码片段,例如把一些小型脚本放到Gist方便分享和管理) 和 github仓库

yarn

  • yarn upgrade–interactive

    更新所有包

前端工程化

模块化开发,打包引用(分块引用加载速度慢,单块开发难度大,耦合性高)

  • 使用export default命令,为模块指定默认输出,在import导入时可以随意指定值

    // 文件 test.js
    let k; export default k = 12; 
    
    // 另一个文件
    import m from './test'; // 由于 k 是默认导出,所以可以自由使用 import m 替代 import k
    console.log(m);        // 输出为 12 

打包(bundle):常见打包工具webpack,rollup,可以根据模块间依赖关系将多个模块合并为一个文件

组件化:UI组件是一组视图及其交互行为的封装,组件化是将页面(或应用),按组件拆分模块开发,通过组件的组合拼装实现页面。

Babel:JavaScript编译器,把ES 2015转成低版本JS语法

css预处理器:支持嵌套和格式复用,如Sass、Less、Stylus,在webpack中增加预处理器loader即可。

TS编译相关

搭配 Babel 和 tsc –watch 使用,前者做文件编译,后者负责类型检查

// package.json
{
  ...
  // 指定输出文件 dist,指定扩展名 "ts,tsx"
  "scripts": {
    "build": "babel src --out-dir dist --extensions \".ts,.tsx\""
    ...
    "check-type": "tsc --watch"
  },
  ...
  "devDependencies": {
    "@babel/cli": "^7.13.16",
    "@babel/core": "^7.13.16",
    "@babel/plugin-proposal-class-properties": "^7.13.0",  // 支持类属性
    "@babel/plugin-proposal-object-rest-spread": "^7.13.8", // 支持剩余扩展操作符
    "@babel/preset-env": "^7.13.15",
    "@babel/preset-typescript": "^7.13.0" // 编译 ts 文件
  }
}

// .babellrc
{
  "presets": ["@babel/preset-env", "@babel/preset-typescript"],
  "plugins": [
    "@babel/plugin-proposal-class-properties",
    "@babel/plugin-proposal-object-rest-spread"
  ]
}

// tsconfig.json
{
  ...
  "compilerOptions":{
    "noEmit":true // 不输出文件,只做类型检查
  }
}

同时另开终端运行 npm run check-type 即可

单元测试

测试金字塔:从低到高是单元测试->服务测试->系统测试,越往上测试数量应该越少

测试框架:AVA、TAPE、Jasmine、Jest

测试框架衡量指标:Node端和Browser的支持,并发的支持,库的集成度,社区的活跃度。Jest最常用

三种编写测试用例形式:xxx.test.js, xxx.spec.js, 或者写到__test__文件夹下,正常.js后缀。

const delay=require('../index');

describe('add 方法测试-__test__', ()=>{
    test('1+1应该等于2', ()=>{
        const res=add(1,1);
        expect(res).toBe(2);
    })
})

describe:将几个相关的测试放到一个组中,非必须

test:别名it,测试用例,是测试的最小单位

expect:提供大量matcher来判断方法返回值是否符合特定条件

异步测试避免没有执行到预期代码,在test的执行方法首行加上断言数expect.assertions(num);,主要是针对异步代码的测试。

并且为了避免过早结束在test末尾添加done()方法,并把test的执行方法调入参数done,表示执行到done()方法后才结束。

针对返回类型为 promise 直接 return 最后调用测试的结果即可。如下:

const delay=require('../index');

test('calllback execute',done=>{
    expect.assertions(1);
    const callback=()=>{
        console.log('callback exec');
        expect(true).toBe(true);
        done();
    };
    delay(callback);
});

test('calllback execute',()=>{
    expect.assertions(1);
    const callback=()=>1;
    return delayPromise(callback).then(res => {
        expect(res).toBe(1);
    });
});

测试覆盖率:在 package.json文件中把scripts行进行修改

"scripts": {
  "test": "jest --coverage"//
},

jest方法:

  • const func = jest.fn().mockReturnValue(1),生成一个返回值为1的函数。

  • 存在库依赖 jest.spyOn 监视库函数

    let mockRandom=null;
    beforeEach(()=>{
        mockRandom=jest.spyOn(Math, 'random');
    })
    
    afterEach(()=>{
        mockRandom.mockRestore();
    })
    
    //设置库函数返回值
    //mockRandom.mockReturnValue(value);
  • jest.mock(‘’)

代码规范

Eslint 和 Prettier

打包之webpack

基础

webpack 默认支持处理 JS 与 JSON 文件,其他类型都处理不了,必须借助 Loader 来对不同类型的文件的进行处理。

配置模块

Entry:入口,指示 Webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。

Output:输出结果,告诉 Webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。

Module

模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。

Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。

Loader:模块代码转换器,让webpack能够去处理除了JS、JSON之外的其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。

Plugin:扩展插件。在webpack运行的生命周期中会广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的api改变输出结果。常见的有:打包优化,资源管理,注入环境变量。

Mode

模式,告知 webpack 使用相应模式的内置优化,默认为 production

选项 描述
development 开发模式,打包更加快速,省了代码优化步骤
production 生产模式,打包比较慢,会开启 tree-shaking 和 压缩代码
none 不使用任何默认优化选项

Browser Compatibility:浏览器兼容性,Webpack 支持所有符合 ES5 标准 的浏览器(IE8以上版本)

打包流程

1、读取webpack的配置参数;

2、启动webpack,创建Compiler对象并开始解析项目;

3、从入口文件(entry)开始解析,并且找到其导入的依赖模块,递归遍历分析,形成依赖关系树;

4、对不同文件类型的依赖模块文件使用对应的Loader进行编译,最终转为Javascript文件;

5、整个过程中webpack会通过发布订阅模式,向外抛出一些hooks,而webpack的插件即可通过监听这些关键的事件节点,执行插件任务进而达到干预输出结果的目的。

NodeJS

环境变量

  • __dirname: 返回当前模块文件解析过后所在的文件夹(目录)的绝对路径。
  • __filename: 返回当前模块文件被解析过后的绝对路径。

设计架构,框架

前端发展和个人发展

“全栈开发者”是指“同时掌握前端、后端以及其他网站开发相关技能的开发者”。

一个“全栈开发者”可能会使用以下技能点:

前端:JavaScript、H5、CSS3、sass、less、React、Vue、Vite(法语意为”快速的”,发音 /vit/ ,发音同”veet”)、webpack、jest。

后端:Nodejs/Deno、Go、Java、Spring、Gin、Kafka、Hadoop。

数据库:MySQL、mongoDB、redis、clickhouse。

运维:网络协议、CDN、Nginx、ZooKeeper、Docker、Kubernetes。

值得注意的是,一个优秀的工程师并不是以“栈”数取胜,而取决于你解决了什么层次的问题。

“全栈”或者“专家”仅仅是实现目标的过程状态。吴军在《硅谷来信》中,将工程师划分成五个等级:工程师5个等级.png从工程师能力模型来看,第一级需要集“天时地利人和”大成,是工程师的最高荣誉。普通人或许可以将目标聚焦在第二、三级。优秀的工程师并不是以“栈”数取胜,更重要的是拥有产品观、全局思维、沟通能力、学习能力、解决问题能力等。来源:《来自未来,2022 年的前端人都在做什么?》

函数化,专注于前端应该做的事情

低代码编程,前端是不可或缺的一环

设计原则

设计系统:设计价值观=>设计原则=>设计风格规范、组件化 Design Token,实现样式代理、资源代理、结构化设计

框架的作用是为前端UI开发提供另外一种方式,提供良好的代码风格,易于添加测试,组件化开发,服务端和客户端路由

无极设计规范:原子设计方法论,拆解和组合

组件化中遇到的问题:组件化不彻底,无基础组件,复用程度低,单位不统一,语法版本规范弱

MVC,包括视图、控制器、模型

MVVM

开发者只需要关心 数据结构 和 视图,抽象层包括视图,视图模型和模型。

实际应用包括Vue、React、San、小程序

真正的区别在于,发布订阅模式实现的是一种多对多的关系,在发布者与订阅者之间需要有一个中介者,发布者发布事件名和参数到中间者,中间者向事件集中的订阅者发送参数。
而观察者是一种一对多的关系,所有的在同一被观察者身上绑定的观察者只能接受同一个被观察者的消息。

本质上,观察者模式和发布订阅模式都是对回调函数的松(解)耦合。回调函数是:事件A结束后,执行事件B。观察者模式实现的是:定义好事件A,事件B,通过“观察”这一行为,将事件A和B的因果先后关系关联起来。发布订阅模式实现的是:事件A结束后,发布到事件中心;事件B订阅A,连同后续回调托管到事件中心。事件中心将A和B关联起来。这一过程中,事件A和事件B完全不会受到对方是否存在的影响,是完全解耦合的。

MTV

model templates view

比如 django

路由

前端/后端路由

router和route,router 可以理解为一个容器,或者说一种机制,它管理了一组 route。简单来说,route 只是进行了URL和函数的映射,而在当接收到一个URL之后,去路由映射表中查找相应的函数,这个过程由 router 来处理。

服务器端路由和客户端路由:

  • 对于服务器来说,当接收到客户端发来的HTTP请求,会根据请求的URL,来找到相应的映射函数,然后执行该函数,并将函数的返回值发送给客户端。在 router 匹配 route 的过程中,不仅会根据URL来匹配,还会根据请求的方法来看是否匹配。如果通过 POST 方法来GET /users的内容,就会找不到正确的路由。
  • 对于客户端(通常为浏览器)来说,路由的映射函数通常是进行一些DOM的显示和隐藏操作。这样,当访问不同的路径的时候,会显示不同的页面组件。有基于Hash和History API两种

上述路由和渲染概念相近。

前端路由——顾名思义,页面跳转的URL规则匹配由前端来控制。而前端路由主要是有两种显示方式:

  • 带有hash的前端路由,优点是兼容性高。缺点是URL带有#号不好看
  • 不带hash的前端路由,优点是URL不带#号,好看。缺点是既需要浏览器支持也需要后端服务器支持

hash/history路由模式

当在url栏中输入新网址,浏览器会直接向服务器请求网址对应的信息。而在已存在网页中点击链接路由时,会进行判断是否需要向服务器请求信息。

hash:带 # 的url,浏览器向服务器请求 # 后的地址信息,仅向服务器请求url中 # 之前的地址,再由浏览器获取到的前端脚本处理#后的地址信息

history:不带 # ,正常 / 分隔,在已加载页面点击链接进行跳转时不会出现问题,当后端服务器不存在某个路由信息而直接在网址栏输入对其访问会404.

前后端通信-Axios

基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

一个通信框架,用于服务器交互;当然也可以使用jQuery提供的AJAX通信功能

  • ajax最早出现的发送后端请求技术,利用用XMLHttpRequest对象。
  • $.ajax是jQuery中的发送后端请求技术,基于原生Ajax的封装。
  • Axios不是原生JS的,需要进行安装。它在client-side和server-side都可以使用。也可以在请求和响应阶段进行拦截。它是基于promise对象的。
  • Fetch号称是AJAX的替代品,使用了ES6中的promise对象。其参数有点像jQuery.ajax。但是fetch不是对ajax的封装,而是原生js实现的,并没有使用XMLHttpRequest对象。

axios 中所谓的绝对路径,就是以 <scheme>://(协议头)或者 // 开头的URL,除此之外都算先对路径,都会在头部附加 baseURL

结构信息

request信息

{
   // `url` 是用于请求的服务器 URL
  url: '/user',

  // `method` 是创建请求时使用的方法
  method: 'get', // default

  // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
  // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
  baseURL: 'https://some-domain.com/api/',

  // `transformRequest` 允许在向服务器发送前,修改请求数据
  // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
  // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
  transformRequest: [function (data, headers) {
    // 对 data 进行任意转换处理
    return data;
  }],

  // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
  transformResponse: [function (data) {
    // 对 data 进行任意转换处理
    return data;
  }],

  // `headers` 是即将被发送的自定义请求头
  headers: {'X-Requested-With': 'XMLHttpRequest'},

  // `params` 是即将与请求一起发送的 URL 参数
  // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
  params: {
    ID: 12345
  },

   // `paramsSerializer` 是一个负责 `params` 序列化的函数
  // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
  paramsSerializer: function(params) {
    return Qs.stringify(params, {arrayFormat: 'brackets'})
  },

  // `data` 是作为请求主体被发送的数据
  // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
  // 在没有设置 `transformRequest` 时,必须是以下类型之一:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - 浏览器专属:FormData, File, Blob
  // - Node 专属: Stream
  data: {
    firstName: 'Fred'
  },

  // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
  // 如果请求话费了超过 `timeout` 的时间,请求将被中断
  timeout: 1000,

   // `withCredentials` 表示跨域请求时是否需要使用凭证
  withCredentials: false, // default

  // `adapter` 允许自定义处理请求,以使测试更轻松
  // 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
  adapter: function (config) {
    /* ... */
  },

 // `auth` 表示应该使用 HTTP 基础验证,并提供凭据
  // 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
  auth: {
    username: 'janedoe',
    password: 's00pers3cret'
  },

   // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
  responseType: 'json', // default

  // `responseEncoding` indicates encoding to use for decoding responses
  // Note: Ignored for `responseType` of 'stream' or client-side requests
  responseEncoding: 'utf8', // default

   // `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
  xsrfCookieName: 'XSRF-TOKEN', // default

  // `xsrfHeaderName` is the name of the http header that carries the xsrf token value
  xsrfHeaderName: 'X-XSRF-TOKEN', // default

   // `onUploadProgress` 允许为上传处理进度事件
  onUploadProgress: function (progressEvent) {
    // Do whatever you want with the native progress event
  },

  // `onDownloadProgress` 允许为下载处理进度事件
  onDownloadProgress: function (progressEvent) {
    // 对原生进度事件的处理
  },

   // `maxContentLength` 定义允许的响应内容的最大尺寸
  maxContentLength: 2000,

  // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject  promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
  validateStatus: function (status) {
    return status >= 200 && status < 300; // default
  },

  // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
  // 如果设置为0,将不会 follow 任何重定向
  maxRedirects: 5, // default

  // `socketPath` defines a UNIX Socket to be used in node.js.
  // e.g. '/var/run/docker.sock' to send requests to the docker daemon.
  // Only either `socketPath` or `proxy` can be specified.
  // If both are specified, `socketPath` is used.
  socketPath: null, // default

  // `httpAgent` 和 `httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
  // `keepAlive` 默认没有启用
  httpAgent: new http.Agent({ keepAlive: true }),
  httpsAgent: new https.Agent({ keepAlive: true }),

  // 'proxy' 定义代理服务器的主机名称和端口
  // `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
  // 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。
  proxy: {
    host: '127.0.0.1',
    port: 9000,
    auth: {
      username: 'mikeymike',
      password: 'rapunz3l'
    }
  },

  // `cancelToken` 指定用于取消请求的 cancel token
  // (查看后面的 Cancellation 这节了解更多)
  cancelToken: new CancelToken(function (cancel) {
  })
}

response信息

{
  // `data` 由服务器提供的响应
  data: {},

  // `status` 来自服务器响应的 HTTP 状态码
  status: 200,

  // `statusText` 来自服务器响应的 HTTP 状态信息
  statusText: 'OK',

  // `headers` 服务器响应的头
  headers: {},

   // `config` 是为请求提供的配置信息
  config: {},
 // 'request'
  // `request` is the request that generated this response
  // It is the last ClientRequest instance in node.js (in redirects)
  // and an XMLHttpRequest instance the browser
  request: {}
}

配置

  • changeOrigin:Boolean

    为false时通过前端访问,devServer转发请求时,http request的host头值不会改变,为true时会把host值改为target指定的host

案例

要求:

  1. 正常请求该有的(跨域携带cookie,token,超时设置)
  2. 请求响应拦截器
    • 请求成功,业务状态码200,解析result给我,我不想一层一层的去判断拿数据
    • http请求200, 业务状态码非200,说明逻辑判断这是不成功的,那就全局message提示服务端的报错
    • http请求非200, 说明http请求都有问题,也全局message提示报错
    • http请求或者业务状态码401都做注销操作
  3. 全局的loading配置,默认开启,可配置关闭(由于后端的问题,经常会让前端加防抖节流或者loading不让用户在界面上疯狂乱点,行吧行吧,你们的问题前端帮你们解决,你的规矩就是规矩是吧🍜)
  4. 统一文件下载处理 (不要再去各写各的下载了,你写一个,他写一个,一个项目就是这样整的跟屎一样)

项目开发流程

一、需求分析

1、需求评审:

时间:在产品设计完成以后,进入正式的开发流程之前,
组织者:产品设计(PM);
目的:统一大家对产品的认识,及时发现产品设计缺陷,尽可能降低后续修改需求的频率;
参与者:后端开发、前端开发、交互设计、视觉设计;需求来源方(有可能的话)
形式:会议

2、需求分析

分析关键功能、应用场景等;基本上在需求评审和分析阶段就对项目的整体实现方案有个基础设计;
对核心功能的实现难度有个清晰的认识、方案不清楚的时候需要提前做好技术调研;
一方面可以给出一个比较准确的排期;另一方面避免了自己在真正开发的时候遇到难以解决的方案,推倒重来,非常狼狈

二、等视觉与交互设计

(很重要,拿不到交互不给排期)

话是这么说,一般排期都等不到视觉交互的交付(前端😭啊);

在这个阶段一般都是要给出项目排期了(多给自己排点填坑的时间)

三、项目开发

(项目完成度基本与视觉设计和交互设计保持一致)

四、预留充分的自测时间

(测试功能和样式)

五、前后端联调

(调接口功能与字段限制);经常需要改接口逻辑、甚至加接口造成前端需要修改对应的校验或功能;时间必须

六、视觉与交互验收

做好开发和自测;视觉与交互的验收很容易;预留一到两天就ok了

七:产品验收;

产品验收很重要、往往他们预计的东西跟设计出来的东西效果是不一致的;甚至会因为实际应用情况需要修改产品设计逻辑 ;需要预留一定时间进行修改

八、提交测试:完成上述步骤之后产品才能提交测试;

保证提测质量(测试周期也会比较长、并且在测试过程中需要及时修改bug、甚至影响业务逻辑的bug需要在一到两个小时之内进行修复)

九、线上接口回归

(后端上线以后需要进行线上接口功能回归之后才能进行上线)

十、新项目的上线前准备

1、资源申请;

2、沙盒环境部署测试(需要进行模拟真实的线上部署测试)

3、线上部署测试(QA进行交付之后、自己需要进行更新迭代测试、保证项目完整可用)

服务器

动态网页的生成是基于动态web server的。一个动态网络服务器首先是一台计算机,这个计算机上包含了产生这个网页所需的HTML模板,样式表,其它托管文件和负责调动这些文件的静态HTTP服务器软件,应用服务器软件和数据库软件(通常情况)。后两者会对HTTP服务器打算传送的托管文件进行更新。

Nginx优点:负载均衡、反向代理、处理静态文件优势。nginx处理静态请求的速度高于apache;

Apache优点:相对于Tomcat服务器来说处理静态文件是它的优势,速度快。Apache是静态解析,适合静态HTML、图片等。

Tomcat:动态解析容器,处理动态请求,是编译JSP\Servlet的容器,Nginx有动态分离机制,静态请求直接就可以通过Nginx处理,动态请求才转发请求到后台交由Tomcat进行处理。

  Apache在处理动态有优势,Nginx并发性比较好,CPU内存占用低,如果rewrite频繁,那还是Apache较适合。

localStorage生命周期是永久,除非主动清除localStorage信息,否则这些信息将永远存在。存放数据大小为一般为5MB,而且它仅在客户端(即浏览器)中保存,不参与和服务器的通信。

sessionStorage仅在当前会话下有效,关闭页面或浏览器后被清除。存放数据大小为一般为5MB,而且它仅在客户端(即浏览器)中保存,不参与和服务器的通信。

cookie机制:如果不在浏览器中设置过期事件,cookie被保存在内存中,生命周期随浏览器的关闭而结束,这种cookie简称为会话cookie。如果在浏览器中设置了cookie的过期事件,cookie会被保存在硬盘中,关闭浏览器后,cookie数据仍然存在,直到过期事件结束才消失。cookie是服务端发给客户端的特殊信息,cookie是以文本的方式保存在客户端,每次请求时都带上它