使用ES6语言
2015年发布的下一代js语言标准,支持不全 所以一般es6编写的代码转化成目前已经支持良好的es5代码,包含以下两件事
- 将新的es6语法用es5实现
- 为新的api注入polyfill
认识Babel
是一个js编译器,将es6代码转化成es5代码,可以通过插件机制灵活扩展 Babel执行变异过程中,会从根目录下的.babelrc文件中读取配置。.babelrc是一个json格式文件,大致内容如下:
{
"plugins": [
[
"transform-runtime",
{
"polyfill": false
}
]
],
"presets": [
[
"es2015",
{
"modules": false
}
],
"stage-2",
"react"
]
}
Plugins
告诉babel要使用哪些插件,这些插件可以控制如何转换代码
transform-runtime对应的插件全名:babel-plugin-transform-runtime,即再前面加上了babel-plugin-,让bable正常运行,安装插件:
npm i -D babel-plugin-transform-runtime
babel-plugin-transform-runtime插件作用是减少冗余代码
- babel在将es6代码转换为es5代码时,通常需要一些有es5编写的辅助函数来完成新语法的实现,如再转换class extent语法时会在转换后的es5代码里注入_extent辅助函数用于实现继承:
function _extent(target) {
for(var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for(var key in source) {
if(Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
}
这会导致每个使用class extent语法的文件都会被注入重复的_extent辅助函数代码
babel-plugin-transform-runtime来了,将原本注入js文件里面的辅助函数替换成一条导入语句var _extent = require(babel-runtime/helpers/_extent');,以此来减小babel编译出来的代码文件大小
babel-plugin-transform-runtime 和 babel-runtime配套使用,使用babel-plugin-transform-runtime后一定回使用babel-runtime,不要忘记安装babel-runtime
Presets
告诉babel要转换的源码使用了哪些新的语法特性
一个Presets对一组新语法的特性提供支持,多个Presets可以叠加 Presets其实是一组Plugins的集合,每个Plugin完成一个新语法的转换工作。
Presets是按照ECMAScript草案来组织的,通常分为三大类
-
已经被写入ECMAScript标准里的:ES2015、ES2016、ES2017、Env 他们的包含关系如下:
-
被社区提出来但还未写入ECMAScript标准里面的:stage0、stage1、stage2、stage3、stage4(美好激进的想法不确定会不会被纳入标准、值得被纳入标准的、特性规范已经被起草将会被纳入的、在接下来一年例会加入标准的)
-
用于支持一些特定场景下的语法的特性,和ECMAScript标准没有关系
接入Babel
通过Loader接入
module.exports = {
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader'],
},
]
},
// 输出source-map以方便直接调试es6源码
devtool: 'source-map'
};
以上配置命中了项目目录下所有js文件。并通过babel-loader调用babel完成转换工作。
在重新执行构建前,需要先安装新引入的依赖:
# Webpack接入Babel必须依赖的模块
npm i -D babel-core babel-loader
# 根据我们的需求选择不同的Plugins或Presets
npm i -D babel-preset-env
使用TypeScript语言
认识TypeScript
TypeScript是js的一个超集,主要提供了类型监察系统和对es6语法的支持,但不支持新的api,目前没有任何环境支持运行原声的ts代码,所以必须通过构建将它转换成js代码后才能运行
ts官方提供了能将ts转化成js的编译器
在项目根目录下新建一个用于配置编译选项的tsconfig.json文件,编译器会默认读取和使用这个文件,内容如下
{
"compilerOptions": {
"module": "commonjs", // 编译出的代码采用的模块规范
"target": "es5", // 编译出的代码采用es的哪个版本
"sourceMap": true // 输出Source Map以方便调试
},
"exclude": [ // 不编译这些目录里的文件
"node_modules"
]
}
通过npm install -g typescript安装编译器到全局后,可以通过tsc hello.ts命令编译出hello.js和hello.js.map文件
减少冗余代码
和babel相似,防止辅助函数重复出现,可以开启ts编译器的importHelpers选项,tsconfig.json修改如下
{
"compilerOptions": {
"importHelpers": true
}
}
原理和babel-plugin-transform-runtime相似,会将辅助函数转换成导入语句
var _tslib = require('tslib');
_tslib._extend(target)
导致编译出的代码依赖tslib这个迷你库,但是避免了冗余代码
集成Webpack
让webpack支持ts,需要解决的问题
- 通过Loader将ts转换成js
- webpack在寻找模块对应文件时需要尝试ts后缀
问题一解决方法:
社区已经出现几个可用的Loader(速度更快的是awesome-typeScript-loader)
问题二解决方法:
修改默认的extensions配置项
webpack配置如下
const path = require('path')
module.exports = {
// 执行入口文件
entry: './main',
output: {
filename: 'bundle.js',
path: path.resolve(_dirname, './dist'),
},
resolve: {
// 先尝试以ts为后缀的typescript源码文件
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
loader: 'awesome-typescript-loader'
}
]
},
detool: 'source-map', // 输出Source Map以方便在浏览器调试ts代码
}
构建前需要安装的依赖:
npm i -D typescript awesome-typescript-loader
使用Flow检查器
认识Flow
是开源的一个js静态类型检查器,是js语言的超集。(在需要的地方加上类型检查) Flow通过类型推断检查出在js代码中潜在的bug 使用效果:
// @flow
// 静态类型检查
function squarel(n: number): number {
return n * n;
}
squarel('2'); // Error: squarel需要传入number作为参数
// 类型推断检查
function squarel2(n) {
return n * n; // Error: 传入的string类型不能做乘法运算
}
squarel('2');
该段代码的第一行// @flow告诉Flow检查器这个文件需要被检查
使用Flow
Flow检查器➡由高性能且跨平台的OCaml语言编写,他的可执行文件可以通过
npm i -D flow-bin安装,安装完成后配置Npm Script:
"scripts": {
"flow": "flow
}
再通过npm run flow执行代码检查。(也可以安装到全局npm i -g flow-bin)
- 采用来Flow静态类型语法的js无法直接在目前已有的js引擎中运行,要让代码可以运行,要将这些静态类型的语法去掉,如:
// 采用Flow的源代码
function f00(one: any, two: number, three?): string {}
// 去掉静态类型语法后输出代码
function foo(one, two, three) {}
有两种方式可以做到这一点
- flow-remove-types:可单独使用,速度快
- babel-preset-flow:与babel集成
集成webpack
使用了Flow的项目一般都会使用es6语法,所以一般借助babel
- 安装
npm i -D babel-preset-flow依赖到项目 - 修改.babelrc配置文件,加入Flow Preset:
"pressets": {
...[],
"flow"
}
向源码加入静态类型后重新构建项目,发现采用了Flow的远吗还是能在浏览器正常运行。 明确构建的目的知识去除源码中的Flow静态类型语法,而代码检查和构建无关。 许多编辑器已经整合了Flow,可以实时在代码中高亮显示Flow检查出的问题。
使用SCSS语言
认识SCSS
一种css预处理器,语法和css相似,但是加入了变量,逻辑等编程元素,代码类似这样
$blue: #1875e7;
div {
color: $blue;
}
scss可以提升编码效率,但是必须将scss源代码编译成可以直接在浏览器匀净下运行的css代码,scss官方提供了以多种语言实现的编译器,就跟着书看一下node-sass
# 安装到全局
npm i -g node-sass
# 执行编译命令
# 将main.scss源文件编译成main.css文件
node-sass main.scss main.css
接入Webpack
webpack官方提供了sass-loader,配置如下
module.exports = {
module: {
rules: [
{
// 增加对scss文件的支持
test: /\.scss/,
// scss文件的处理顺序先sass-loader,再css-loader,再style-loader
use: ['style-loader', 'css-loader', 'sass-loader'],
}
]
}
}
具体处理流程讲解:
- 通过sass-loader将scss文件转化成css代码,再将css代码交给css-loader处理
- css-loader会找出css代码中@import和url() 这样的导入语句,告诉webpack依赖这些资源,同时支持css modules,压缩css等功能,处理完交给style-loader处理
- style-loader将css代码转化成字符串后,注入js代码中,通过js向dom增加样式;(如果我们将xss代码提取到一个单独文件中,而不是和js混在一起,则可以使用ExtractTextPlugin)
由于接入sass-loader,所以项目需要安装新的依赖
# 安装webpackLoader依赖
npm i -D sass-loader css-loader style-loader
# sass-loader依赖node-sass
npm i -D node-sass
使用PostCSS
认识PostCSS
是一个CSS处理工具,不同于SASS的是它可以通过插件灵活扩展其支持的属性 (可以项css自动加前缀,使用下一代css语法等)
- postcss和css的关系就像babel和js的关系,解除了语法上的禁锢,通过插件机制扩展语言本身
- postcss和sass的关系像babel和ts的关系,postcss更灵活,可扩张性强,scss内置了大量的功能但不能扩展 举个栗子: 1、为css自动增加前缀
/* 输入 */
h1 {
display: flex;
}
/* 输出 */
h1 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
2、使用下一代语法
/* 输入 */
:root {
--red: #d33;
}
h1 {
color: var(--red);
}
/* 输出 */
h1 {
color: #d33;
}
使用postcss启动,从postcss.config.js文件读取所需要的配置,所以需要新建该文件,文件大致内容如下
module.exports = {
plugins: [
// 需要使用的插件列表
require('postcss-cssnext')
]
}
// postcss-cssnext插件可以让我们使用下一代css语法编写代码
接入webpack
使用了postcss后,文件的后缀还是.css,单必须将这些文件先交给postcss-loader处理一遍后再交给css-loader
module.exports = {
module: {
rules: [
{
// 使用PostCSS处理CSS文件
test: /\.css/,
use: ['style-loader', 'css-loader', 'postcss-loader']
},
]
},
}
介入PostCSS需要安装的依赖
# 安装webpack loader依赖
npm i -D poatcss-loader css-loader style-loader
# 根据我们使用的特性安装对应的postcss依赖
npm i -D postcss-cssnext