同构
指的是数学对象之间属性或者操作关系的一类映射,数学中的通过主要是为了把数学知识应用到更多不同领域,同理,javascript中的同构主要是为了把javascript知识应用到更多不同领域,简单来说就是令javascript代码可以运行在浏览器和nodejs中工作
传统网站的渲染流程是由浏览器主动发起请求,然后由服务器生成HTML文档发送响应到浏览器,浏览器接收到之后渲染为可视化网页.在客户端终端设备以及浏览器性能普遍比较落后的情况下都能保证良好的渲染效果,并且服务端渲染更便于SEO,缺点是每访问一个页面都要发起请求,每个请求都需要服务器进行路由匹配,数据库查询,生成页面在发送给浏览器,这个过程会消耗服务器大量的计算资源
随着个人终端设备和浏览器性能不断提升,web开发者尝试将渲染以及路由工作交给客户端,RESTFul API只提供渲染所需的数据,这种形态被称为SPA
优点: 1. 减轻服务器资源消耗 2. 与HTML文档相比,json体积更小,减少网络请求时间 3.页面路由控制更加灵活 4.可以离线使用
缺点: 1.浏览器需等待js文件加载完成才可以渲染html文档内容,会出现白屏效果 2.客户端和服务器编程语言不同,存在诸多的格式差异,甚至路由逻辑冲突 3.SEO不友好,谷歌已针对SPA进行了优化,但国内的搜索引擎对SPA的支持并不理想
动态资源和静态资源
静态资源指的是js,css,图片等,这种资源是静态的,不需要服务器做处理,动态资源指的是html模板
- html模板处理方案:
- SPA项目: 这类项目不存在html模板概念,所有html实体内容均由js在浏览器下生成,所以SPA项目可以将html作为静态文件处理
- html模板由服务端部署的项目: 这类项目最终的html模板需要与服务端代码一同打包部署,静态文件必须由html引入,开发阶段直接编写html模板更利于快速开发和问题定位
- 大前端项目,这类项目前端负责所有客户端文件,包含静态文件和html模板
- 部署方案
- 将静态资源部署到静态文件服务器
- html模板文件与中间层node一同部署到web服务器
SPA项目部署方案稍微复杂一些,SPA中html文件不需要在服务端渲染,理论上是可以部署到静态服务器,但是不能令浏览器将html文件强制缓存到本地,可行的做法:
- 分别为html与其他静态文件设置不同的缓存策略,html文件可以使用协商缓存(状态码304),静态资源就使用强缓存策略(状态码200)
- 所有资源都采用协商缓存处理
前后端分离工程化会遇到哪些问题?
- 想使用最新的es6规范进行开发,但浏览器受限,上线前需要进行语法转换
- css弱编程语言,想使用最新的less/sass等预编译语言或者postCss自动处理的hack
- 本地开发环境下静态资源引入url都是本地相对地址,上线前要修改为真是url
- 考虑产品性能问题,上线前将js,css图片等资源进行压缩,需要使用css,或者将小体积图片通过base64格式内嵌
- 模块化开发能够提高web产品性能和源代码维护效率,模块上线前需要进行依赖分析与合并打包
- 编写js逻辑代码时候需要与数据接口交互
- 开发层面上:
- es规范与浏览器不兼容
- css的弱编程能力
- 资源定位
- 图片压缩/base64/css Sprites
- 模块依赖分析和压缩打包
- 协作层面
js部分依赖接口api
- 部署层面
部分资源需要后端协助部署
前端工程化3个阶段
- 工具链
工程化核心并非工具,前端工程化以规范工作流程作为手段,以工具实现作为媒介,最终目的是为了提高研发效率及保证线上质量.
- 规范
- 项目文件组织结构
- 源代码开发范式,比如使用既定的方案
- 工具的使用规范
- 各阶段环境的依赖,比如部署功能的实现需要目标服务器提供ssh权限
- 管理平台
- 比如系统类型,操作版本,内核等,这些因素会在一定程度上影响构建产出代码的一致性
- 权限控制
- 工程化平台需要做到以下几点:
- 淡化环境差异性,保证构建产出的一致性
- 权限集中管理,提高安全性
- 项目版本集中管理,便于危机处理,版本回滚
- 持续集成–> 融入整体
前端工程化本质是将前端和后端工程师的工作解耦,虽然提升了工作效率,但各自的工作流是独立的,比如生产环境版本回滚,前后端需要对自己维护的代码进行操作,并且保证回滚的同步性,前端工程化只是web工作流中的一个子集方案,最终的完美形态必然是与整体工作流结合
模块化
- commonjs
通过require实现同步加载依赖的其他模块,通过module.exports导出模块,优点:1.代码可复用于node环境下运行,通过npm发布的很多第三方模块都采用了commonjs规范
- AMD
与commonjs不同的是,它采用异步方式去加载依赖的模块,在使用时需要先导入实现AMD的库才能正常使用
// 定义一个模块
define("module",['dep'],function(){ return exports})
// 导入和使用
require(['module'],function(module){})
- es6模块化
es6虽然是终极模块化方案,但是缺点是目前无法直接运行大部分js环境,必须通过es5转换后才能正常运行
// 导入
import {xxx} from 'xxx'
// 导出
export function xxx(){}
- 样式文件中的模块化
@import 导入和使用片段
构建要做的事情
- 代码转换: es6->es5,less->css,sass->css,stylus->css
- 文件优化: 压缩js,css,html代码,压缩合并图片
- 模块合并: 模块化项目中有很多模块和文件,将构建功能和模块合并成一个文件
- 代码分割
- 自动刷新
- 代码校验
- 自动发布
webpack
1.1 loader
loader: 可以看作是具有文件转换功能的翻译员
rules:[
{
test: /\.css$/,
use:['style-loader','css-loader?minimize']
}
]
1.2 plugin
plugin是webpack的扩展插件
plugins:[
new HtmlWebpackPlugin({
filename:'index.html',
})
]
1.3 devServer
- 监听模式: 页面修改后,浏览器自动刷新
- 模块热替换: 相对于默认的刷新机制进行更快更好的响应速度和开发体验
- source Map: 编译的文件可读性很差,通过source map可以知道编译后的代码和源代码的对应关系,方便调试
- 核心概念
1.1 Entry: 入口
1.2 Module: 模块,在webpack中一切皆模块,一个模块对应一个文件
1.3 Chunk: 代码块,一个chunk由多个模块组合,用于代码合并与分割
1.4 Loader: 模块转换器,用于转换非js模块为js模块
1.5 Plugin: 插件,用于扩展webpack功能
1.6 Ouput: 输出