从 1 到圆满,写一个 js 库、node 库、前端组件库
之前讲了许多关于项目工程化、前端架构、前端构建等方面的手艺,此次说说怎样写一个圆满的第三方库。
1. 挑选适宜的范例来写代码
js
模块化的生长大抵有如许一个历程 iife => commonjs/amd => es6
,而在这几个范例中:
-
iife
:js
原生支撑,但平常不会直接运用这类范例写代码 -
amd
:requirejs
定义的加载范例,但随着构建东西的涌现,便平常不会用这类范例写代码 -
commonjs
:node
的模块加载范例,平常会用这类范例写node
顺序 -
es6
:ECMAScript2015
定义的模块加载范例,但到目前为止,险些一切的js
运转环境都不支撑,包含浏览器、node
(包含electron
、nw.js
)、React Native
等
针对原生不支撑任何范例的运转环境顺序(如浏览器、React Native
),发起运用 es6
范例来写代码,然后由东西转换成原生 js
能够运转的。
而针对 node
顺序,能够直接用 commonjs
范例来写,也可由 es6
范例来写,然后用东西转化成 commonjs
范例。
所以,总的来讲,都能够运用 es6
范例来写代码,然后用东西转换成其他范例,而且 es6
的代码能够运用 tree-shaking
功用。
参考:
2. 挑选适宜的构建东西
关于前端项目来讲,由于有静态资本(如图片、字体等)加载与按需加载的需求,所以运用 webpack
是不贰挑选,但关于第三方库来讲,实在另有更好的挑选:rollup
。
能够检察 webpack 以外的另一种挑选:rollup 相识 webpack
与 rollup
之间各自的差别与上风。
webpack
在打包成第三方库的时刻只能导出 amd/commonjs/umd
,而 rollup
能够导出 amd/commonjs/umd/es6
。运用 rollup
导出 es6
模块,就能够在运用这个库的项目中构建时运用 tree-shaking
功用。
关于有款式文件(css
、less
、scss
)、静态资本文件(图片、字体)的前端组件来讲,能够运用 rollup-plugin-postcss 插件合营 rollup
处置惩罚款式文件与静态资本文件。
参考:
- webpack、rollup、rollup-plugin-postcss
- webpack 以外的另一种挑选:rollup
- UMD (Universal Module Definition)
- tree-shaking
- webpack 怎样文雅的运用tree-shaking(摇树优化)
3. 定好目次构造
平常库项目的目次:
|-- / # 项目根目次
|-- src/ # 源代码目次
|-- lib/(dist/) # 宣布文件目次
|-- test/ # 测试文件目次
|-- ... # 更多其他目次
假如是多包项目(一个项目里有多个 npm packages,比方 babel):
|-- / # 项目根目次
|-- packages/ # packages 目次
|-- pkg1/ # package1 目次
|-- src/ # 源代码目次
|-- lib/(dist/) # 宣布文件目次
|-- pkg2/ # package2 目次
|-- src/ # 源代码目次
|-- lib/(dist/) # 宣布文件目次
|-- ...
后面会细致解说多包项目。
4. 搭建一个好的脚手架
不管是运用项目照样第三方库项目,都须要搭建一个好的脚手架,来协助我们更好的编写代码、构建项目等。
能够检察 搭建本身的前端脚手架 相识一些基础的脚手架文件与东西。
比方:
-
.editorconfig
: 用这个文件来一致差别编辑器的一些设置,比方tab
转 2 个空格、自动插进去空尾行、去掉行尾的空格等,http://editorconfig.org - eslint、stylelint、prettier: 范例化代码作风、优化代码花样等
- husky、lint-staged: 在
git
提交之前对代码举行检察,不然不予提交 -
.travis.yml
: 一个很棒的延续集成效劳,https://www.travis-ci.org/
细致的文件、东西与设置,参考 搭建本身的前端脚手架。
别的,针对开源的第三方库,还能够有:
-
LICENSE
: 协定文件 -
CONTRIBUTING.md
: 项目代码参与者 -
codecov.yml
: 测试覆蓋率设置文件 -
.github
:github
上的一些自定义设置,比方issue
模板、pr
模板等 -
/docs
: 文档目次 -
/examples
: 运用示例目次 -
/scripts
: 剧本目次
加上 rollup
的设置文件 rollup.config.js
:
rollup.config.js
假如是 node
顺序,把 es6
范例转化成 commonjs
范例:
export default {
input: 'src/index.js',
output: {
file: 'lib/index.js',
format: 'cjs',
},
};
假如是前端库,还须要转 es6+
到 es5
、导出差别范例的文件(es6/commonjs/amd/umd
):
import babel from 'rollup-plugin-babel';
import postcss from 'rollup-plugin-postcss';
export default [
{
file: 'lib/cjs.js',
format: 'cjs',
},
{
file: 'lib/m.js',
format: 'esm',
},
{
file: 'lib/umd.js',
format: 'umd',
name: 'Name',
},
{
file: 'lib/amd.js',
format: 'amd',
},
].map(output => ({
input: 'src/index.js',
output,
plugins: [
babel({
presets: ['@babel/preset-env'],
}),
postcss({ extract: !0 }), // 构建款式文件时须要这个插件
],
}));
.gitignore
平常来讲,我们并不愿望把宣布文件放到 git
的版本掌握当中,而只是宣布到堆栈罢了,所以:
# .gitignore
.DS_Store
node_modules
bower_components
/coverage
*.log
.idea
.vscode
.eslintcache
package-lock.json
/lib # 把 lib 消除在外
/packages/*/lib # 多包项目
package.json
{
...
# node 项目
"main": "lib/index.js",
# 前端项目
"main": "lib/cjs.js", # commonjs 范例文件
"module": "lib/m.js", # es6 范例文件
"umd:main": "lib/umd.js", # umd 范例文件
"amd:main": "lib/amd.js", # amd 范例文件
"files": [ # 宣布时只宣布 lib 目次下文件
"lib"
],
"scripts": {
...
"build": "rollup -c", # 构建宣布文件
"prepublishOnly": "npm run build", # npm publish 之前先 npm run build
"pretest": "npm run build", # npm run test 之前先 npm run build
},
...
}
在现实项目中,构建东西(如 webpack
)会首先找这个包中的 module
字段对应的 es6
范例文件,并运用 tree-shaking
;假如不存在,然后找 main
字段对应的文件。
有些构建东西能够也会用 amd
范例文件与 umd
范例文件。
参考:
5. 构建多包项目
假如一个项目很大,须要分割成多个 npm
包举行治理,但这些包仍然在一个项目里,而且这些包能够有相互依靠关联,这个时刻就比较难以治理和开发了。
为了轻易的治理多包项目,lerna 便应运而生,babel、create-react-app、jest、lila 等都是用 lerna
来治理多个包的。
英文不好的童鞋,能够参考 运用lerna治理大型前端项目,相识 lerna
的一些基础用法。
lerna 平常目次文件构造
my-lerna-repo/
package.json
packages/
package-1/
package.json
package-2/
package.json
装置 lerna,初始化项目
# 装置
npm i -g lerna
# 初始化
git init lerna-repo && cd lerna-repo
lerna init
# 初始化后的目次及文件
lerna-repo/
packages/
package.json
lerna.json
设置文件 lerna.json
{
"version": "0.5.2", # 当前版本号
"packages": [
"packages/*"
],
"command": {
"publish": { # 宣布设置
"ignoreChanges": [ # 哪些文件更改不会激发宣布新版本
"*.md",
"*.json",
"*.txt",
"test/**",
"example/**",
"package.json"
]
},
"bootstrap": {
"npmClient": "cnpm" # lerna bootstrap 时运用哪一个 npm 客户端
}
},
"npmClientArgs": [ # npm 客户端 运转时的参数
"--no-package-lock"
]
}
常用敕令
lerna publish
: 宣布一切有更新的包
在默许的牢固形式(Fixed mode)下,这个敕令会搜检 packages
目次下哪些包的文件有更新(lerna.json
中 command.publish.ignoreChanges
除外),然后把 lerna.json
中的 version
与有更新的包中 package.json
的 version
字段更新到一个新的版本号上,末了把这些有更新的包都宣布到长途堆栈上。
lerna bootstrap
: 启动竖立包相互之间的 node_modules
链接
这个敕令会依据各个包下 package.json
内里的 dependencies
和 devDependencies
设置,运用 symlink
在各个包的 node_modules
下面竖立援用关联。如许就处理了相互之间有依靠而没法联调的题目。
lerna changed
: 检察哪些包有更新,能够宣布一个新的版本
lerna diff [package?]
: 检察包都更新了些什么
lerna run [script]
: 运用 npm
运转每一个包下面的 [script]
参考:
6. 示例
单个包的 node
项目能够参考我的项目:sclean
单个包的前端项目能够参考我的项目:see-fetch
多个包的项目能够参考我的项目:lila
后续
更多博客,检察 https://github.com/senntyou/blogs
版权声明:自在转载-非商用-非衍生-坚持签名(创意同享3.0许可证)