(1)模块化
1.CommonJS
CommonJS是一种被广泛使用的Javascript模块化规范,其核心思想是通过require方法来同步加载依赖的其他模块,通过module.exports导出需要暴露的接口。
2.AMD
与CommonJS最大的不同在于,它采用了异步的方式去加载依赖的模块。主要用于解决针对浏览器环境的模块化问题,最具代表性的实现是requirejs。
3.ES6模块化
ES6模块化是国际标准化组织ECMA提出的JavaScript模块化规范,它在语言层面上实现了模块化。
4.样式文件中的模块化
以SCSS为例,将一些常用的样式片段放进一个通用文件里,再在另一个文件里通过@import语句导入使用。
(2)新框架
1.React
React框架引入了JSX语法到JavaScript语言层面中,可以更灵活地控制视图的渲染逻辑。
2.Vue
Vue框架将与一个组件相关的HTML模版、Javascript逻辑代码、CSS样式代码都写在一个文件里。
3.Angular2
Angular2推崇采用TypeScript语言开发应用,并且可以通过注解的语法描述组件的各种属性。
(3)新语言
1.ES6
新特性:规范模块化、Class语法、let、const、箭头函数、async函数、Set和Map数据结构。
2.TypeScript
TypeScript是JavaScript的一个超集,由Microsoft开发并开源,除了支持ES6的所有功能,还提供了静态类型检查。缺点是语法相对于Javascript更啰嗦,并且无法在浏览器或Node.js环境下直接运行。
3.Flow
Flow也是Javascript的一个超集,主要特点是为Javascript提供静态类型检查。
4.SCSS
SCSS可以让我们用程序员的方式写CSS。它是一个CSS预处理器,其基本思想是用和CSS相似的编程语言写完后再编译成正常的CSS文件。
采用SCSS写CSS的好处在于可以方便地管理代码,抽离公共的部分,通过逻辑写出更灵活的代码。
(4)构建
构建就是将源代码转换成可执行的Javascript、CSS、HTML代码,包括如下内容:
1.代码转换:将Typescript编译成Javascript、将SCSS编译成CSS等;
2.文件优化:压缩Javascript、CSS、HTML代码,压缩合并图片等;
3.代码分割:提取多个页面的公共代码,提取首屏不需要执行的代码让其异步加载;
4.模块合并
5.自动刷新
6.代码校验
7.自动发布
(5)构建工具
1.Npm Script
Npm Script是一个任务执行者,是npm内置的一个功能。
2.Grunt
Grunt和Npm script类似,也是一个任务执行者。Grunt有大量现成的插件封装了常见的任务,也能管理任务之间的依赖关系,自动化地执行依赖的任务,每个任务的具体执行代码和依赖关系写在配置文件Gruntfile.js里。
3.Gulp
Gulp是一个基于流的自动化构建工具。除了可以管理和执行任务,还支持监听文件、读写文件。
4.Fis3
Fis3是一个来自百度的优秀国产构建工具。相对于Grunt、Gulp这些只提供了基本功能的工具,Fis3集成了Web开发中的常用构建功能:读写文件、资源定位、文件指纹、压缩资源、图片合并。
5.Webpack
Webpack是一个打包模块化Javascript的工具,在webpack里一切文件皆模块,通过Loader转换文件,通过Plugin注入钩子,最后输出由多个模块组合成的文件。
webpack的缺点是只能用于采用模块化开发的项目。
6.Rollup
Rollup是一个和webpack很类似但专注于ES6的模块打包工具。它是在webpack流行后出现的,但生态链不如webpack。
(6)安装webpack、使用loader、使用plugin、使用DevServer
(1)Entry
1.context
webpack在寻找相对路径的文件时会以context为根目录,context默认为执行启动webpack时所在的当前工作目录。
2.Chunk的名称
webpack会为每个生成的Chunk取一个名称,如果entry是一个string或array,则chunk的名称是main,如果entry是一个object,则是object中键的名称。
(2)Output
1.filename
filename: ‘[name].js’ [name]为Chunk的名称。
2.path
output.path配置输出文件存放在本地的目录,必须是string类型的绝对路径。
3.publickPath
在复杂的项目里可能会有一些构建出的资源需要异步加载,加载这些异步资源需要对应的URL地址。output.publicPath配置发布到线上资源的URL前缀,为string类型。
(3)Module
1.配置Loader
rules配置模块的读取和解析规则,通常用来配置Loader。
Include(只查找相应目录下的文件)、exclude(排除相应目录下的文件)
2.noParse
noParse配置项可以让webpack忽略对部分没采用模块化的文件的递归解析和处理,原因是一些库如jQuery庞大又没有采用模块化标准,让webpack去解析这些文件既耗时又没有意义。
(4)Resolve
webpack在启动后会从配置的入口模块出发找出所有依赖的模块,Resolve配置webpack如何寻找模块所对应的文件。
1.alias
通过别名来将原导入路径替换成新的导入路径。
2.extensions
在导入语句没带文件后缀时,webpack会自动带上后缀去尝试访问文件是否存在。
(5)Plugin
(6)DevServer
1.hot
开启模块热替换功能,将在不刷新整个页面的情况下通过用新模块替换老模块来做到实时预览。
2.historyApiFallback
用于方便地开发使用了HTML5 History API的单页应用。
3.contentBase
配置DevServer HTTP服务器的文件根目录。
4.https
DevServer默认使用HTTP服务,它也能使用HTTPS服务。
5.clientLogLevel
配置客户端的日志等级,可能取值如下:none、error、warning、info。
6.compress
配置是否启用Gzip压缩。
7.open
用于在DevServer启动且第一次构建完时,自动用我们的系统的默认浏览器去打开要开发的网页。
(7)Target
Target配置项可以让webpack构建出针对不同运行环境的代码。
(8)Devtool
devtool配置webpack如何生成Source Map。
(9)Watch和WatchOptions
配置监听模式
(10)Externals
Externals用来告诉在webpack要构建的代码中使用了哪些不用被打包的模块,也就是说这些模块是外部环境提供的,webpack在打包时可以忽略它们。
(11)ResolveLoader
用来告诉webpack如何去寻找Loader,该配置项常用于加载本地的Loader。
(12)多种配置类型
1.多个环境写多个配置文件
2.导出一个Function
3.导出一个返回Promise的函数
4.导出多份配置
(1)使用ES6语言
1.bablerc文件
在Bable执行编译的过程中,会从项目根目录下的.bablerc文件中读取配置。
plugins属性告诉Babel要使用哪些插件,这些插件可以控制如何转换代码。
presets属性告诉Babel要转换的源码使用了哪些新的语法特性。
(2)使用TypeScript语言
TypeScript是JavaScript的一个超集,主要提供了类型检查系统和对ES6语法的支持。
TypeScript官方提供了能将TypeScript转换成JavaScript的编译器,我们需要在当前项目的根目录下新建一个用于配置编译选项的tsconfig.json文件,编译器默认会读取和使用这个文件。
(3)使用Flow检查器
Flow是Facebook开源的一个Javascript静态类型检测器,它是Javascript语言的超集。
(4)使用SCSS语言
SCSS又叫做SASS,区别在于SASS语法类似于Ruby,而SCSS语法类似于CSS。采用SCSS去写CSS的好处在于,可以方便地管理代码,抽离公共的部分,通过逻辑写出更灵活的代码。
(5)使用PostCSS
PostCSS是一个CSS处理工具,和SCSS的不同之处在于它可以通过插件机制灵活地扩展其支持的特性,而不像SCSS那样语法是固定的。
(6)使用React框架
(7)使用Vue框架
(8)使用Angular2框架
与React和Vue相比,Angular2要复杂的多,这三者的出发点都是组件化和数据驱动视图,但Angular2多出了以下概念:模块、注解、服务、依赖注入。
(9)为单页应用生成HTML
(10)管理多个单页应用
(11)构建同构应用
同构应用是指写一份代码但可同时在浏览器和服务器中运行的应用。同构应用的运行原理的核心在于虚拟DOM,虚拟DOM的意思是不直接操作DOM,而是通过Javascript Object描述原本的DOM结构。在需要更新DOM时不直接操作DOM树,而是在更新Javascript Object后再映射成DOM操作。
(12)构建Electron应用
Electron可以让我们使用开发Web的技术去开发跨平台的桌面端应用,它是Node.js和Chromium浏览器的结合体,用Chromium浏览器显示出的web页面作为应用的GUI,通过Node.js和操作系统交互。
(13)构建npm模块
Npm是目前最大的Javascript模块仓库
(14)构建离线应用
离线应用的核心是离线缓存技术,历史上出现过两种离线缓存技术,Application Cache(目前已从web标准中删除)、service workers(是web worker的一部分,它通过拦截网络请求实现离线缓存,比AppCache更灵活,它也是构建PWA应用的关键技术之一)。
(15)搭配Npm Script
(16)检查代码
ESlint、TSLint、stylelint
(17)通过Node.js API启动Webpack
(18)使用Webpack Dev Middleware
(19)加载图片
1.使用file-loader
2.url-loader:可以将文件的内容经过base64编码后注入javascript或者css中
(20)加载SVG
(21)加载Source Map
优化可以分为优化开发体验和优化输出质量两部分。
(1)缩小文件的搜索范围
1.优化Loader配置
由于Loader对文件的转换操作很耗时,所以需要尽可能少的文件被Loader处理,可以通过test、include、exclude三个配置项来命中Loader要应用规则的文件。
2.优化resolve.modules配置
它用于配置webpack去哪些目录下寻找第三方模块。
3.优化resolve.mainFields配置
它用于配置第三方模块使用哪个入口文件。
4.优化resolve.alias配置
5.优化resolve.extensions配置
6.优化module.noParse配置
module.noParse配置项可以让webpack忽略对部分没采用模块化的文件的递归解析处理,这样做的好处是能提高构建性能。
(2)使用DllPlugin
Web项目构建接入动态链接库的思想后,会大大提升构建速度。
(3)使用HappyPack
文件读写和计算操作是无法避免的,那能不能让webpack在同一时刻处理多个任务,发挥多核CPU电脑的功能,以提升构建速度呢?HappyPack它将任务分解给多个子进程去并发执行,子进程处理完后再将结果发送给主进程。
(4)使用ParallelUglifyPlugin
将多个文件的压缩工作分配给多个子进程完成,每个子进程其实还是通过UglifyJS去压缩代码,但是变成了并行执行。
(5)使用自动刷新
在webpack中监听一个文件发生变化的原理,是定时获取这个文件的最后编辑时间,每次都存下最新的最后编辑时间,如果发现当前获取的和最后一次保存的最后编辑时间不一致,就认为该文件发生了变化。
webpack模块负责监听文件,webpack-dev-server模块负责刷新浏览器。
通过禁止向每个chunk中都注入DevServer的代理客户端实现优化。
(6)开启模块热替换
模块热替换的原理和自动刷新的原理类似,都需要向要开发的网页中注入一个代理客户端来连接DevServer和网页。
(7)区分环境
DefinePlugin
(8)压缩代码
设置更为详细的压缩选项来优化。
(9)CDN加速
CDN的作用就是加速网络传输,通过将资源部署到世界各地,使用户在访问时按照就近原则从离其最近的服务器上获取资源,来加快资源的获取速度。
针对CDN缓存问题,业界比较成熟的做法如下:
针对HTML文件:不开启缓存,将HTML放到自己的服务器上,而不是CDN服务上,同时关闭自己服务器上的缓存。针对静态的js、css、图片文件:开启CDN和缓存,上传到CDN服务上,同时为每个文件名带上由文件内容算出的Hash值,这样文件内容变化就会被重新下载。
webpack配置核心是通过publicPath参数设置存放静态资源的CDN目录URL。
(10)使用Tree Shaking
Tree Shaking可以用来剔除Javascript中用不上的死代码,它依赖静态的ES6模块化语法,例如通过import和export导入、导出。
(11)提取公共代码
CommonsChunkPlugin
(12)分割代码以按需加载
使用import()分割代码。
(13)使用Prepack
Prepack由Facebook开源,采用了较为激进的方法,在保持运行结果一致的情况下,改变源代码的运行逻辑,输出性能更好的Javascript代码,实际上,Prepack就是一个部分求值器,编译代码时提前将计算结果放到编译后的代码中,而不是在运行时才去求值。
(14)开启Scope Hoisting
Scope hoisting可以让webpack打包出来的代码文件更小、运行更快,它的实现原理很简单:分析模块之间的依赖关系,尽可能将被打散的模块合并到一个函数中。
(15)输出分析
webpack官方提供了一个可视化分析工具Webpack Analyse,它是一个在线web应用。
(1)工作原理概括
几个概念:
Entry:入口,webpack执行构建的第一步将从Entry开始,可抽象成输入;
Module:模块,在webpack里一切皆模块,一个模块对应一个文件。webpack会从配置的Entry开始,递归找出所有依赖的模块;
Chunk:代码块,一个Chunk由多个模块组合而成,用于代码合并与分割;
Loader:模块转换器,用于将模块的原内容按照需求转换成新内容;
Plugin:扩展插件,在webpack构建流程中的特定时机会广播对应的事件,插件可以监听这些事件的发生,在特定的时机做对应的事情。
流程:
初始化参数->开始编译->确定入口->编译模块->完成模块编译->输出资源->输出完成。
(2)输出文件分析
(3)编写Loader
1.Loader基础
一个Loader其实就是一个Node.js模块,这个模块需要导出一个函数。这个导出的函数的工作就是获得处理前的原内容,对原内容执行处理后,返回处理后的内容。
2.Loader进阶
获得Loader的options、返回其他结果、同步与异步、处理二进制数据、缓存加速等
(4)编写Plugin
在webpack运行的生命周期中会广播许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的API改变输出结果。
在开发Plugin时最常用的两个对象就是Compiler和Compilation,Compiler对象包含了Webpack环境的所有配置信息,包含options、loaders、plugins等;Compilation对象包含了当前的模块资源、编译生成资源、变化的文件等。区别在于Compiler代表了整个webpack从启动到关闭的生命周期,而Compilation只代表一次新的编译。可以直接在Compiler和Compilation对象上广播和监听事件。
常用API:
读取输出资源、代码块、模块及其依赖;
监听文件的变化;
修改输出资源;
判断webpack使用了哪些插件;