包管理器
- lerna (用于项目分成多个项目包的时候,多包管理工具)
- rollup(模块捆绑工具)
- Rome(校验封装等统一独立工具为一体的工具)
- Snowpack(非捆绑,快速的包管理工具)
Lerna(用于管理多包的JS项目的工具)
前情提要
将大型代码库分成单独的独立版本化的软件包对于代码共享非常有用。但是,跨那么多存储库进行更改很麻烦且难以跟踪,并且跨存储库的测试变得非常复杂。
为了解决这些(以及许多其他)问题,一些项目会将其代码库组织到多包存储库中。Babel,React,Angular,Ember,Meteor,Jest等项目以及其他许多项目都在单个存储库中开发了所有软件包。
Lerna是一种工具,可以优化使用git和npm管理多包存储库的工作流程。
创建
npm install --global lerna //全局安装lerna
git init lerna-repo && cd lerna-repo //创建并初始化lerna-repo,并进入该存储库目录
lerna init // 初始化或将现有的仓库升级成Lerna当前的版本
指令
lerna bootstrap //引导Lerna数据库中的数据包,安装它们的所有依赖性并链接任何交叉依赖性。
lerna bootstrap
这条指令十分重要,引导数据包后,它可以让你通过require()
使用软件包名称,就好像这些数据包已经存在于你的node_modules
一样
lerna import <本地路径> //将本地路径中的包导入具有提交历史记录的 数据包/目录 中
lerna publish //创建一个新版本的已经更新的软件包,并更新git和npm上的所有软件包
选项:
--npm-tag[标签名] //给这一次更新添加一个标签名并发布到npm上
--canary //创造一个快照
--skip-git //不运行任何git命令
--force-publish [数据包名] //强制发布指定的软件包(以逗号分隔)或用*使用于所有软件包(跳过git diff检查已更改的软件包)
lerna changed //检查有哪些软件包已经更改
lerna diff [软件包名] //比较所有的软件包或者单个软件包
lerna run [脚本] //运行每一个包中含有的这个脚本
lerna ls //列出当前lerna存储库中的所有公共软件包
Lerna依赖是什么样的?
他结构十分的简单:
my-lerna-repo/
package.json
packages/
package-1/
package.json
package-2/
package.json
Lerna能做什么?
Lerna的特点主要突出在两个指令lerna bootstrap
和lerna publish
,前者把仓库中的依赖项链接在一起,后者有助于发布任何更新的软件包
Lerna不能做什么?
Lerna不是一个针对无服务器单机的部署工具,依赖提升可能会让可能与传统的无服务器的单机部署技术不兼容。
Lerna的依赖提升(–hoist)
当将整个项目划分为多个NPM包时,这种组织改进通常是有代价的——各种包在其Package.json文件中通常有许多重复的依赖项,因此在各个node_module目录中有成百上千个重复的文件。 通过Lerna使管理由许多NPM包组成的项目变得更容易,Lerna可能会在不经意间加剧这个问题。
幸运的是,Lerna还提供了一个特性来改善这种情况——Lerna可以通过将依赖项“提升”到最顶层的Lerna项目级node_module目录来减少开发和构建环境中大量包副本的时间和空间需求。
–hoist在使用中应该是透明的,这是一种运行时优化,理想情况下不需要对项目进行任何其他修改。 使用–hoist标志时
共同的依赖项就只安装到顶级的node_module,并从各个包node_module中省略
大多数常见的依赖项仍然会被提升,但是本地的node_module包还是会得到一个正常的,安装着必要的依赖项
在这个情况中,无论客户机配置如何,
Lerna bootstrap
都会始终使用带有--global-style
标志的npm install
。这些通用软件包中的二进制文件被符号链接到各个软件包
node_modules/.bin
目录,因此package.json
脚本可以不修改地继续工作。行为良好的基于Node的软件应继续工作,无需修改。
rollup(JS的模块捆绑工具)
前情提要
Rollup是JavaScript的模块捆绑器,它将小段代码编译成更大更复杂的东西,如库或应用程序。 它对JavaScript的ES6修订版中包含的代码模块使用新的标准化格式,而不是以前的特殊解决方案,如CommonJS和AMD。 ES模块允许您自由、无缝地组合您喜爱的库中最有用的单个函数。
安装
npm install --global rollup
这些命令假定应用程序的入口点名为main.js,并且您希望所有导入都被编译到一个名为bundle.js的文件中。
对于浏览器:
#编译为包含自执行功能
汇总的<script> main.js --format iife --name “ myBundle ” --file bundle.js
对于Node.js:
#编译为CommonJS模块
汇总main.js --format cjs --file bundle.js
对于浏览器和Node.js:
# UMD格式需要一个包名称
汇总main.js --format UMD --name “ myBundle ” --file bundle.js
为什么要使用rollup
如果将项目拆分成更小的独立部分,开发软件通常会更容易,因为这通常会消除意外的交互,并极大地降低需要解决的问题的复杂性,而简单地编写较小的项目并不一定就是解决问题的办法。 遗憾的是,JavaScript在历史上并没有将此功能作为核心功能包含在语言中。
最终由于JavaScript中的ES模块支持而发生了变化,JavaScript提供了用于导入和导出函数和数据的语法,以便可以在单独的脚本之间共享它们。现在,该规范已在所有主要浏览器中以及在“ .mjs”文件的–experimental-modules标志后面的Node.js中实现。汇总允许您使用此模块系统编写代码,或者输出优化的ES模块以供在这些本机环境中使用,或者将其编译回现有支持的格式,例如CommonJS模块,AMD模块和IIFE样式的脚本。
Tree-shaking
除了支持使用ES模块之外,汇总还可以静态分析您要导入的代码,并将排除任何未实际使用的内容。这使您可以在现有工具和模块的基础上进行构建,而无需增加额外的依赖关系或增加项目的规模。
例如,对于CommonJS,必须导入整个工具或库。
// import the entire utils object with CommonJS
const utils = require( './utils' );
const query = 'Rollup';
// use the ajax method of the utils object
utils.ajax(`https://api.example.com?search=${query}`).then(handleResponse);
使用ES模块,无需导入整个utils
对象,而只需导入所需的一个ajax
功能:
// import the ajax function with an ES6 import statement
import { ajax } from './utils';
const query = 'Rollup';
// call the ajax function
ajax(`https://api.example.com?search=${query}`).then(handleResponse);
因为汇总包括最低限度的内容,所以它可以使库和应用程序更轻,更快,更简单。由于此方法可以利用显式import
和export
语句,因此它比简单地运行自动缩小器来检测已编译输出代码中未使用的变量要有效。
Rome(多个独立校验文件的封装)
是什么?
Rome是JavaScript、TypeScript、JSON、HTML、Markdown和CSS的链接器、编译器、绑定器等。
Rome被设计用来取代Babel, ESLint, webpack, Prettier, Jest等。
Rome统一了以前是独立工具的功能。在共享的基础上构建允许我们提供处理代码、显示错误、并行工作、缓存和配置的内聚体验。
Rome是用TypeScript编写的,运行在Node.js上。罗马没有任何依赖性,而且很大程度上是从零开始编写的。
克隆(clone)并构建
Rome 目前无法通过 npm
安装,必须从 GitHub 上下载源码才能安装。 选择一个空目录,然后克隆 rome
源码仓库:
git clone https://github.com/romejs/rome
然后,进入该目录并构建 rome
:
cd rome; ./scripts/build-release dist
在 Windows 10 系统上,请在 PowerShell 7 中运行如下命令:
cd rome && node scripts/build-release dist
然后,将 rome
安装到全局环境:
npm install -g ./dist/
相关命令
rome run
命令将运行传递过来的任何文件。 将此命令作用于你的项目的主文件,例如:
rome run index.js
rome lint
命令将使用一组默认的 lints 来检测某个文件并显示诊断信息。 不带任何参数运行此命令时,将对当前项目中的所有 JavaScript 文件做代码检测。例如:
rome lint file.js
rome compile
命令将使用一组默认转换(transforms)来编译文件。目前此命令没有用于指定转换子集(subset of transforms)的参数。rome parse
命令将解析文件并输出格式美观的抽象语法树(AST)。
rome parse file.js
Snowpack(非捆绑,开发速度快)
Snowpack是啥?
Snowpack是一个用于更快web开发的现代前端构建工具。它取代了开发工作流中更重、更复杂的包(如webpack或Parcel)。
Snowpack利用JavaScript的本机模块系统(称为ESM)创建了第一个从不两次构建相同文件的构建系统。Snowpack立即将更改推送到浏览器,节省了您在传统上等待bundler的开发时间。
特点
- 使用50毫秒或更短时间内启动的开发服务器,开发速度更快。
- 查看更改立即反映在浏览器中。
- 集成您最喜欢的捆绑器,以优化生产。
- 享受对TypeScript,JSX,CSS模块等的现成支持
- 将您喜欢的工具与第三方插件连接。
Snowpack是怎么运作的?
Snowpack是一款用于更快web开发的现代轻量级构建工具。
传统的JavaScript构建工具如webpack
和Parcel
需要在每次保存单个文件时重建和重新打包整个应用程序块。这个重新绑定的步骤会在点击保存更改和在浏览器中看到它们之间产生延迟。(捆绑)
Snowpack在开发期间为您的应用程序提供解捆绑服务。每个文件只需要构建一次,然后被永久缓存。当一个文件发生变化时,Snowpack会重新构建这个文件。重新打包每一项更改不需要浪费时间,只需在浏览器中进行即时更新(通过热模块替换(HMR)速度更快)。(非捆绑)
Snowpack的非捆绑开发仍然支持与您习惯用于生产的相同的捆绑构建。当你要构建你的产品应用程序时,你可以通过官方的Webpack或Rollup插件(即将推出)插入你最喜欢的打包。由于Snowpack已经可以处理您的构建,所以不需要复杂的打包配置。
Snowpack实现了两全其美:在捆绑的产品构建中实现了性能优化的快速、非捆绑开发。
安装
#使用 npm
npm install --save-dev snowpack
#使用 yarn
yarn add --dev snowpack
启动
#启动dev服务器,在本地加载站点
snowpack dev
#构建用于生产的站点
snowpack build
#构建站点,监控文件系统,并在文件更改时重建(适合本地开发)
snowpack build --watch
捆绑式开发和非捆绑式开发
非捆绑开发是在开发过程中将单个文件传送到浏览器的想法。仍然可以使用您喜欢的工具(例如Babel,TypeScript,Sass)来构建文件,然后借助ESMimport
和export
语法将它们与依赖项分别加载到浏览器中。每当您更改文件时,Snowpack都只需要重建当前这个文件就可以了。(翻译一下就是:哪里改动重新构建哪个文件)
替代方法是捆绑开发。如今,几乎所有流行的JavaScript构建工具都将重点放在捆绑开发上。通过捆绑程序运行整个应用程序会给开发工作流程带来额外的工作和复杂性,由于ESM得到了广泛的支持,因此这是不必要的。必须将所有更改(每次保存)与应用程序的其余部分重新捆绑在一起,然后更改才能在浏览器中反映出来。(翻译一下就是:一旦有一个地方改动,要整个程序进行重新构建)
与传统的捆绑开发方法相比,非捆绑开发具有多个优点:
- 单文件构建速度很快。
- 单文件构建是确定性的。
- 单文件版本更易于调试。
- 项目规模不会影响开发速度。
- 单个文件缓存更好。
最后一点很关键:每个文件都是单独构建的并无限期地缓存。您的开发环境将永远不会多次构建文件,浏览器也不会下载两次文件(直到更改)。这是非捆绑式开发的真正力量。