1, 包管理工具
对于一⻔成熟的语言来说,在有语言规范的同时,社区或者制定语言规范的组织也会有模块化的规范和模块存储到平台,每个人都能将自己写好的模块化代码发布到平台上,同时任何人也可以下载公共平台上其他人的模块化代码。这种模块化的代码一般称为包
,平台称为包管理平台
,这种行为称为包管理
对于 JS
来说,有 node.js 环境自带的 npm
工具,即 node.js 的包管理工具,对于一个符合规范的包来说,我们可以通过 npm publish
发布包,也可以通过 npm install
下载别人发布的包.
社区中常⻅的包管理工具有,bower
、npm
、yarn
1, bower
bower 最早出现是使用在浏览器项目中。安装 bower 命令后,通过 bower install xxx
就可以将 xxx 下载到 bower_components
目录中,我们就可以在 html
文件加上 <script src="bower_components/xxx/dist/xxx.min.js"></script>
。免去了我们直接从官网下载然后挪动到项目中的烦恼。
bower 也支持一些配置,我们只需要在项目根目录下增加 .bowerrc 配置即可:
{
"directory": "app/components/",
"timeout": 120000,
"registry": {
"search": [
"http://localhost:8000",
"https://registry.bower.io"
]
}
}
以上代码,主要配置了我们下载后的模块存储目录,下载超时时间和下载的地址等。
如果想要发布一个 bower 模块
的话,需要我们这个项目下配置 bower.json
,然后通过 bower register
命令发布.
2, npm
npm 是伴随着 node.js 下载会一同安装的一个命令
,它的作用与 bower 一样,都是下载或发布一些 JS 模块。
我们可以使用 npm --version
查看安装的 npm 版本,不同版本带有不同功能, 还可以通过 npm install xxx
来安装一个模块,npm 会将模块安装到 node_modules 目录中。
一个合格的 npm 包,必须拥有 package.json
文件,里面有以下几个常⻅字段:
name: 包名 (比如jQuery包,name: "jQuery")
version: 版本
main(重要): 默认加载的入口文件
scripts: 定义一些脚本
dependencies: 运行时需要的模块
devDependencies:本地开发需要运行的模块
optionalDependencies: 可选的模块,即使安装失败安装进程也会正常退出
peerDependencies:必要依赖的版本版本
其中 dependencies 和 devDependencies 里面的版本号通过 大版本.次要版本.小版本
的格式规定。
如果前面带有波浪号(~),则以大版本号和次要版本号为主
,例如 "~1.3.2" 的版本,最终安装时就会 安装 1.3.x 的最新版本。
如果前面带有插入号(^),则以大版本号为主
,例如 "^1.3.2" 的版本,最终安装就会安装 1.x.x 的最新 版本。
所有下载的模块,最终都会记录在 package-lock.json 完全锁定版本,下次我们再 npm install 时,就会先下载 package-lock 里面的版本
3, yarn
yarn 管理工具,与 npm 有着相似的功能,最大的优势就是并发、快.
通过 yarn add
进行安装一个模块,通过 yarn xxx
来运行 scripts 中的脚本。
4, 包管理工具中常⻅面试题
1,devDependencies、dependencies、optionalDependencies 和 peerDependencies 区别:
- devDependencies 是指使用本地开发时需要使用的模块,而真正的业务运行时并不需要它
- dependencies 是指业务运行时需要的模块
- optionalDependencies 是可选模块,安不安装均可,即使安装失败,包的安装过程也不会报错
- peerDependencies 一般用在大型框架和库的插件上,例如我们写 webpack--xx-plugin 的时候,对于使用者而言,他一定会先有 webpack 再安装我们的这个模块,这里的 peerDependencies 就是约束了这个例子中 webpack 的版本。
2,npm 中 --save-dev 和 --save 的区别
对于大型项目来说,他们的界限实际上并不清晰。真正会有差异的地方是究竟我们使用哪种式来进行安装所有的依赖。
- save-dev 和 save 都会把模块安装到 node_modules 目录下,但 save-dev 会将依赖名称和版本写到 devDependencies 下
- 而 save 会将依赖名称和版本写到 dependencies 下。
- 如果我们使用 npm --production install 这样的命令安装模块的话,就只会安装 save 安装的包。
2,格式化工具、源代码静态检查
静态检查:是我们在本地写源代码时,我们使用的编辑器对我们所写代码的提示,检查和格式化。
在大型项目中,提示这一步因人而异,大部分不做过多要求,检查和格式化一般会对团队使用的内容进行约束,以保证大家能写出正确的代码和统一的代码⻛格。
代码的检查和格式化,比较经典的是 jslint
、jshint
、eslint
、 prettier
,基本上都是一类的工具,再细分的话,jslint、jshint、eslint 是一类,它们专⻔处理 JS 格式化和静态语法检查
,prettier 是另一类,他能处理多语言的格式化
1, eslint (https://eslint.org/)
我们以 eslint 为例,只需要在项目中通过 npm install --save-dev eslint
安装,通过配置 .eslintrc
就可以使用了, 配合 eslint 的编辑器插件,我们就可以在编辑代码时 eslint 对我们的代码进行提示和修复。
通过配置 eslint index.js 这样的脚本,就可以对脚本文件进行静态校验。
注意这里是 --save-dev 因为我们只需要在项目开发过程中使用它而不是运行过程使用这个模块。
2, prettier (https://prettier.io/)
同样的我们可以配置 prettier 的配置, .prettierrc 里面也可以 进行配置,最终搭配 prettier 的编辑器插件,我们同样能够实现代码编辑状态下的提示和修复。
3, 编译 (ES6及其他泛 JS 语言的编译)
大部分时候,我们不能直接在线上使用 ES6 语法规范的 JS 代码,我们就需要通过工具对 JS 进行编译。 同时,有些项目我们可能会使用 coffeescript,typescript,flow,elm,ocaml 等可以编译为 JS 语言 的泛 JS 语言书写代码,这就需要在调试或发布时,使用编译工具将对应代码编译为 JS 代码才能直接运行。
在编译过程中,JS 比较常⻅的工具是 babel,而其他的语言则对应有自己的编译器,例如 coffeescript 使用 coffeescript 编译器进行编译为 js,typescript 使用 typescript 编译器编译为 js。
1, babel (https://babeljs.io/)
对于一个项目来说,我们可以通过 npm install --save-dev @babel/core @babel/cli
来安装 babel 所需要的工具。
- @babel/core: 是 babel 内部核心的编译和生成代码的方法
- @babel/cli:是 babel 命令行工具内部解析相关方法
安装了这两个包之后,我们就能够使用 babel 相关方法对代码进行操作,接下来我们需要配置,告诉babel 我们需要将代码变成什么
增加一个 babel 的 preset,preset 代表的是我们希望编译的结果的预设值。在最新的 babel 工具链中,统一使用了 @babel/preset-env
作为环境预设值。我们安装 npm install --save-dev @babel/preset-env
之后,新建 .babelrc
里面,通过配置:
{
"presets": ["@babel/preset-env"]
}
在 scripts 内定义一个脚本执行 babel index.js -o output.js ,我们在 index.js 中写的 es6 语法 就会被编译。
这一步只是编译语法层面的内容,如果我们使用了一些新的方法的话,还需要增加一个 polyfill, 使用 npm install @babel/polyfill
安装了所有符合规范的 polyfill 之后,我们需要在入口文件引入这个模块,就能正常的使用规范中定义的方法了
JS 打包工具
对于 JS 这⻔语言的不同环境来说,有 CommonJS,AMD 和 ESModule 这几种常⻅的模块化规范,这几种规范都有自身的缺点。
CommonJS 不经处理只能运行在 node.js,AMD 不经处理无法运用在各个平台,需要搭配符合 AMD 规 范的其他库例如 require.js 一起使用。ESModule 虽然从语言层面上解决了规范问题,但是即使经过 babel 编译,也会将 import,export 之类的关键词编译为 CommonJS 的 require 和 exports ,我们还是无法直接在浏览器中使用。
为了能使任何一个模块都能自由的切换所使用的环境,例如在浏览器使用 CommonJS 封装好的模块, 我们就需要经过打包这个步骤。
browserify
、 rollup
等工具都是处理诸如此类内容
1, browserify (http://browserify.org/)
ify 使xx化
我们通过 npm install --save-dev browserify
安装 browserify, 我们写一个简单的 commonJS 模块,通过 browserify index.js -o output.js 命令就可以将 CommonJS 模块化的包转化为通用的任何环境均可以加载的模块化规范。
运用:
// index.html 引入output.js
// index.js
var module = require('./module.js')
console.log(module.str)
// module.js
exports.str = 'xiaownag'
控制台执行:browserify index.js -o output.js即可生成一个 output.js 文件
未打包之前代码运行:
image使用browserify打包后:
image2, rollup
rollup 是一个新兴的打包工具,它最先提出一个概念叫 tree shaking,他可以移除我们代码中无用的其他代码。
通过 ESModule 写的模块,在经过 rollup 处理之后,会对未使用的导出内容进行标记,在压缩过程就会将这类未使用的内容移除。
JS 压缩⼯具
经过编译和打包的 JS 代码,最终要在线上经过压缩处理之后,才能最终在⽹站上⾯向⽤户显示。对于
JS 压缩⼯具来说,⽬前有⾮常多,但⽤的最多的还是 uglify 系列,uglify 最新是版本 3,不同 uglify 的
实现原理和性能都有极⼤的不同。
uglify (https://github.com/mishoo/UglifyJS2)
安装成功之后⾮常简单,只需要通过 uglifyjs index.js -o output.js
就可以输出压缩的结果。
同时我们可以通过添加 --source-map 在运⾏时⽣成 sitemap ⽂件,⽅便我们进⾏ debug
其他类⽬⼯具
任务处理⼯具(gulp/grunt)
上⾯我们说的所有⼯具都是针对某⼀个垂直领域来说的,⽐如 编译
、打包
、压缩
等,我们需要通过不同的命令去运⾏和操作我们的 JS ⽂件。
任务处理⼯具,就是这⼀类脚本⼯具,他们能通过脚本的形式将不同的⼯具进⾏组合输出。
流式处理⼯具⽐较常说的两个是 grunt 和 gulp
1, grunt (https://gruntjs.com/)
⾸先通过 npm install --save-dev grunt
安装 grunt ⼯具,新建 gruntfile.js
通过 gruntfile.js 中的配置来让 grunt 做不同的操作。
这⾥我们安装 npm --save-dev @babel/core @babel/preset-env grunt-babel gruntcontrib-uglify
来完整的进⾏⼀个项⽬的构建,通过配置 gruntfile 脚本,我们分别执⾏了编译
、压缩
的过程⽣成最后 js 脚本
2, gulp (https://gulpjs.com/)
同样的我们使⽤ npm install --save-dev gulp
安装 gulp ⼯具,新建 gulpfile.js
配置。
我们同样实现相同的功能来重新配置⼀下 gulp 任务。
gulp 相⽐于 grunt 来说,配置更加清晰,是⼀个链式调⽤的写法
通⽤处理⼯具(fis3/webpack)
通⽤处理⼯具这⾥我们的分类是从功能上来讲,具备上⾯列举类⽬的多种功能的集合。这⾥我们列举的
⼏个⼯具是 fis3 和 webpack。
fis 是国内百度公司在早期发布的⼀款前端通⽤处理⼯具(⽐ webpack 早),fis3 是它的第三代,使⽤
node.js 重写了。
fis3 和 webpack 他们有个最⼤的特点就是,他们已经不再是⼀个普通⼯具,⽽是⼀个具有插件化的系
统,有着丰富和完善的社区环境,他们属于前端解决⽅案这么⼀个领域。理论上他们可以做⾮常多的
事情,⽽不像上⾯介绍的⼤部分⼯具,只能处理某⼀个垂直分类下的内容。
webpack 实际上和 gulp grunt 这类的任务处理⼯具有些类似,但是它本身具有打包
的功能,同时也⽀
持通过中间件和插件实现其他领域的功能,最终通过⼀个命令就能处理完成所有操作。
webpack 通过 webpack.config.js 配置,配置 loader 中间件来对不同⽂件进⾏操作,同时通过插件化
的配置,⽀持例如压缩
等等操作。
使⽤ fis3 和 webpack,他们更多的是将前⾯我们讲的所有其他⼯具融合起来,以⼀种插件的形式进⾏
加载,从⽽达到了通⽤的⽬的。
网友评论