以前讲了不少关于项目工程化、前端架构、前端构建等方面的技术,此次说说怎么写一个完美的第三方库。css
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
而针对 node
程序,能够直接用 commonjs
规范来写,也可由 es6
规范来写,而后用工具转化成 commonjs
规范。react
因此,总的来讲,均可以使用 es6
规范来写代码,而后用工具转换成其余规范,并且 es6
的代码可使用 tree-shaking
功能。webpack
参考:git
对于前端项目来讲,由于有静态资源(如图片、字体等)加载与按需加载的需求,因此使用 webpack
是不二选择,但对于第三方库来讲,其实还有更好的选择:rollup
。es6
能够查看 webpack 以外的另外一种选择:rollup 了解 webpack
与 rollup
之间各自的差别与优点。github
webpack
在打包成第三方库的时候只能导出 amd/commonjs/umd
,而 rollup
可以导出 amd/commonjs/umd/es6
。使用 rollup
导出 es6
模块,就能够在使用这个库的项目中构建时使用 tree-shaking
功能。 web
对于有样式文件(css
、less
、scss
)、静态资源文件(图片、字体)的前端组件来讲,可使用 rollup-plugin-postcss 插件配合 rollup
处理样式文件与静态资源文件。express
参考:
通常库项目的目录:
|-- / # 项目根目录 |-- src/ # 源代码目录 |-- lib/(dist/) # 发布文件目录 |-- test/ # 测试文件目录 |-- ... # 更多其余目录
若是是多包项目(一个项目里有多个 npm packages,好比 babel):
|-- / # 项目根目录 |-- packages/ # packages 目录 |-- pkg1/ # package1 目录 |-- src/ # 源代码目录 |-- lib/(dist/) # 发布文件目录 |-- pkg2/ # package2 目录 |-- src/ # 源代码目录 |-- lib/(dist/) # 发布文件目录 |-- ...
后面会详细讲解多包项目。
不论是应用项目仍是第三方库项目,都须要搭建一个好的脚手架,来帮助咱们更好的编写代码、构建项目等。
能够查看 搭建本身的前端脚手架 了解一些基本的脚手架文件与工具。
好比:
.editorconfig
: 用这个文件来统一不一样编辑器的一些配置,好比 tab
转 2 个空格、自动插入空尾行、去掉行尾的空格等,http://editorconfig.org git
提交以前对代码进行审查,不然不予提交.travis.yml
: 一个很棒的持续集成服务,https://www.travis-ci.org/ 详细的文件、工具与配置,参考 搭建本身的前端脚手架。
另外,针对开源的第三方库,还能够有:
LICENSE
: 协议文件CONTRIBUTING.md
: 项目代码参与者codecov.yml
: 测试覆盖率配置文件.github
: github
上的一些自定义配置,好比 issue
模板、pr
模板等/docs
: 文档目录/examples
: 使用示例目录/scripts
: 脚本目录加上 rollup
的配置文件 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 }), // 构建样式文件时须要这个插件 ], }));
通常来讲,咱们并不但愿把发布文件放到 git
的版本控制之中,而只是发布到仓库而已,因此:
# .gitignore .DS_Store node_modules bower_components /coverage *.log .idea .vscode .eslintcache package-lock.json /lib # 把 lib 排除在外 /packages/*/lib # 多包项目
{ ... # 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
规范文件。
参考:
若是一个项目很大,须要分割成多个 npm
包进行管理,但这些包仍然在一个项目里,而且这些包可能有相互依赖关系,这个时候就比较难以管理和开发了。
为了方便的管理多包项目,lerna 便应运而生,babel、create-react-app、jest、lila 等都是用 lerna
来管理多个包的。
英文很差的童鞋,能够参考 使用lerna管理大型前端项目,了解 lerna
的一些基本用法。
my-lerna-repo/ package.json packages/ package-1/ package.json package-2/ package.json
# 安装 npm i -g lerna
# 初始化 git init lerna-repo && cd lerna-repo lerna init
# 初始化后的目录及文件 lerna-repo/ packages/ package.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]
参考:
单个包的 node
项目能够参考个人项目:sclean
单个包的前端项目能够参考个人项目:see-fetch
多个包的项目能够参考个人项目:lila
更多博客,查看 https://github.com/senntyou/blogs
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)