Skip to main content

· One min read
tip

CSS-doodle 是一个基于 Web-Component 的库。允许我们快速的创建基于 CSS Grid 布局的页面,以实现各种 CSS 效果(或许可以称之为 CSS 艺术)

· One min read

Details element example

Toggle me!
This is the detailed content

Nested toggle! 内含惊喜……
😲😲😲😲😲

mdx export

Docusaurus 绿Facebook 蓝 是我最喜欢的颜色。

mdx import

Easy to Use

Easy to Use

Docusaurus was designed from the ground up to be easily installed and used to get your website up and running quickly.

Focus on What Matters

Focus on What Matters

Docusaurus lets you focus on your docs, and we'll do the chores. Go ahead and move your docs into the docs directory.

Powered by React

Powered by React

Extend or customize your website layout by reusing React. Docusaurus can be extended while reusing the same header and footer.

这是个苹果 🍎
在告示中使用选项卡
这是个苹果 🍎

mdx全局作用域

MDXComponents

· 4 min read

1. Homebrew

tip

mac安装软件使用brew,安装完brew后注意终端的提示,需要操作两步设置brew的path node、git等尽量都别手动安装,不然卸载很痛苦~

  • brew help
  • brew list
  • brew install
  • brew update
  • brew uninstall

2. vscode的code命令

  • 打开VSCode –> command+shift+p –> 输入shell command –> 点击提示Shell Command: Install ‘code’ command in PATH运行
  • 打开终端,cd到要用VSCode打开的文件夹,然后输入命令code .即可打开

3. 右键打开终端

在文件(夹)上右键--->服务--->新建位于文件夹位置的终端窗口

4. 显示(或者隐藏)隐藏的文件

Shift+Command+(.)

5. 卸载手动安装的node

  • 运行如下命令: sudo rm -rf /usr/local/{lib/node{,/.npm,_modules},bin,share/man}/{npm*,node*,man1/node*}

  • 您必须注意,如果您运行此特定命令,您并没有实现完整的卸载 Node 任务。 那是因为主目录或主目录不会受到影响。 因此,通过这种方式,您仍然必须删除在您的主目录中找到的相关文件和文件夹。

  • 之后,您必须删除使用 NPM 安装的每个全局包。 为此,请在终端上运行以下命令rm –rf ~/.npm。 键入引号中的命令后,您将完成在 Mac 上卸载 Node 和卸载 NPM 的任务。

6. 远程连接

  • ssh 连接远程服务器
    • 执行 ssh 服务器用户名@服务器ip,然后输入密码
  • sftp 可以上传文件到远程或者从远程下载文件,例如:要将本地的b文件夹(a/b/c.txt) 放到 远程e/f下面

    • 在远程e/f下 mkdir b
    • 在本地cd a
    • 执行 sftp 服务器用户名@服务器ip,然后输入密码
    • cd e/f/
    • 执行 put -pr b (要保留修改时间、访问时间以及被传输的文件的模式,请使用 -p 标志;-r 参数允许拷贝子目录和子文件)
    • 退出 sftp: 使用 bye 或者 quit 或者 exit
  • sftp的一些命令

    • get remotefile [localfile] 远程文件传输到本地。
    • mkdir directory 创建一个远程目录。
    • rmdir path 删除一个远程目录。
warning

使用 put 命令,如果目录名称不存在于远程主机上的工作目录中,可能会报错。所以,首先在远程主机上创建一个具有相同名称的目录,然后从本地主机上传它。

7. kill端口号

sudo lsof -i :<PortNumber>

kill -9 <PID>

8. 鼠标方向调整

tip

系统偏好设置--->鼠标--->勾掉 滚动方向:自然

9. vscode快捷键

  • Shift + Option + F 格式化代码
  • Ctrl + - 返回上一步

10. 可视化查看/usr /tmp /var /etc等目录

进入“访达”的偏好设置,选择“边栏”,勾中“硬盘”,再使用Shift+Command+(.)显示隐藏文件

11. 截屏

Shift ⇧ + Command ⌘ + 5

12. 快速查看

若要在不打开文件的情况下查看其预览,请选择文件,然后按下空格键。

· 7 min read

monorepo

2024 年 Monorepo 工具选择和实践

Monorepo 的这些坑,我们帮你踩过了!

微前端场景下的代码共享

基于 Rush 的 Monorepo 多包发布实践

从微组件到代码共享

使用monorepo的知名开源库

Changesets

Changesets: 流行的 monorepo 场景发包工具

tip

在版本控制系统中,"changeset"是一个术语,指的是一组在单个提交中引入的更改。每个 "changeset" 都有一个唯一的标识符,通常称为"版本号"或"修订号"。这个标识符可以是数字、字符串或者数字和字符串的组合,用于追踪特定的更改集。

Changesets 是一个用于版本管理和发布的工具,特别适用于处理 monorepo 中的多个包。它通过变更文件(changesets)来跟踪对每个包的更改,并在发布时自动更新版本号和生成 changelog。以下是如何使用 Changesets 的基本步骤:

  1. 安装 Changesets CLI: 在你的项目中安装 @changesets/cli 作为开发依赖。

    npm install @changesets/cli --save-dev
    # 或者使用 yarn
    yarn add @changesets/cli --dev
  2. 初始化 Changesets: 运行 changeset init 来初始化 Changesets 配置。这将创建一个 .changeset 目录和一些配置文件。"changeset"文件也会在该目录下生成。

    npx changeset init
  3. 创建变更文件: 当你对包进行更改时,你需要记录这些更改。运行 changeset 命令来创建一个新的变更文件(即"changeset"文件)。

    npx changeset

    这将提示你选择更改的包、更改的类型(major、minor、patch)以及更改的描述。这些信息将被用来生成 changelog 和更新版本号。

    注意:此时只是记录变更信息,不会更新package.json 文件中的版本号。

  4. 审查变更文件: 变更文件将被添加到 .changeset 目录中。你可以审查这些文件以确保更改记录正确。

  5. 当你准备好发布时,运行 changeset version 命令来应用变更文件中的更改,并更新包的版本号。

    npx changeset version

    这将更新 package.json 文件和 CHANGELOG.md 文件,以记录这些更改的详细信息。

    同时,相应的变更文件(即"changeset"文件)被消耗,即会被自动删除。

  6. 发布到 npm: 运行 changeset publish 命令来发布更新的包到 npm。

    npx changeset publish

    这将自动根据更新的版本号发布包,并将变更文件移动到 .changeset/README.md 中。

确保在使用 Changesets 之前,你的包已经在 package.json 中正确配置了版本号和发布设置。此外,如果你在 monorepo 中使用 Changesets,你可能还需要配置 yarn workspacesnpm workspaces 来确保依赖关系正确处理。

如果你的项目是一个 monorepo,并且使用了像 Yarn Workspaces 或 npm Workspaces 这样的工具,你需要确保根目录的 package.json 被包含在工作区(workspaces)的配置中。这样,Changesets才会更新项目根目录下的 package.json 的版本。请注意,如果你的根目录下的 package.json 不代表一个可发布的包,而只是用于管理 monorepo 的配置和脚本,那么你可能不需要(也不应该)使用 @changesets/cli 来更新它的版本号。在这种情况下,版本号可能没有实际的意义,因为它不会被发布到 npm。

"Bump version" 是一个术语,通常指在软件开发中增加软件的版本号。这个过程可以是手动的,也可以通过自动化工具来完成。版本号通常遵循语义化版本控制(Semantic Versioning,简称 SemVer),它包括三个部分:主版本号(major)、次版本号(minor)和修订号(patch)。

  • 主版本号:当你做了不兼容的 API 修改时,需要增加主版本号。

  • 次版本号:当你以向下兼容的方式添加功能时,需要增加次版本号。

  • 修订号:当你做了向下兼容的问题修正时,需要增加修订号。

版本号的增加通常与软件的新发布相对应,可能包括新功能的添加、bug 修复或其他更新。

在自动化工具中,如 npm versionyarn version 或使用 lernachangesets 等工具时,"bump version" 过程通常包括以下步骤:

  1. 更新 package.json 文件中的版本号。
  2. 创建一个新的 Git 标签来标记这个版本。
  3. 可能还会更新 CHANGELOG 文件,列出自上次发布以来的所有更改。

例如,使用 npm 来 bump 版本的命令如下:

npm version patch # 增加修订号
npm version minor # 增加次版本号
npm version major # 增加主版本号

这些命令会自动更新 package.json 中的版本号,并根据需要创建一个新的 Git 标签。

· 16 min read

package.json

官方配置

main

main字段指定了当包被引入时(例如,通过requireimport语句)应该默认加载的模块文件。这个字段通常用于指向包的主入口点。

如下,当用户执行require('some-package')import相应的模块时,Node.js将会默认加载index.js文件。如果main字段没有被指定,Node.js会默认查找包根目录下的index.js文件。

{
"name": "some-package",
"version": "1.0.0",
"main": "index.js"
}

main字段是可选的,但是指定它可以让你的包更加清晰地表明其入口点是哪个文件,尤其是当你的主文件不叫index.js时。

files

package.json文件中,files字段是一个数组,它指定了哪些文件和目录应该包含在你的npm包中。当你发布一个包到npm时,files数组可以用来过滤包含在你的包中的内容,确保只有重要的文件被上传,而不必要的或敏感的文件(如配置文件、测试文件、文档等)被排除在外。

如下,当你运行npm publish发布你的包时,只有lib目录和index.js文件会被包含在你的npm包中。所有其他文件和目录都会被忽略。

{
"name": "your-package",
"version": "1.0.0",
"files": [
"lib/",
"index.js"
]
}

如果你没有在package.json中指定files字段,npm会默认包含所有目录下的文件,除了那些通过.npmignore文件或.gitignore文件(如果没有.npmignore文件)明确忽略的文件。还有一些文件和目录总是会被忽略,比如.gitnode_modules等。

bin

bin字段用于定义一个或多个可执行文件的映射。这些可执行文件是项目提供的命令行工具或脚本。当你的包被安装为全局包(使用npm install -g)或者作为其他项目的依赖时,这些可执行文件会被链接到系统的路径中,使得用户可以直接通过命令行调用它们。

如下,当my-cool-package被安装后,my-cool-command将会被链接到系统路径。用户可以在命令行中直接运行my-cool-command来执行./bin/my-cool-command.js文件。

{
"name": "my-cool-package",
"version": "1.0.0",
"bin": {
"my-cool-command": "./bin/my-cool-command.js"
}
}

如果你只有一个可执行文件,你也可以直接提供一个字符串而不是对象,在这种情况下,可执行命令的名称将默认使用包的名称。

{
"name": "my-cool-package",
"version": "1.0.0",
"bin": "./bin/my-cool-command.js"
}

private

如果你在 package.json 中设置了 "private": true ,那么 npm 将拒绝发布它。

这是防止意外发布私人存储库的一种方法。如果您想确保给定的包仅发布到特定registry(例如内部registry),请使用 publishConfig 在发布时覆盖registry的配置参数。

publishConfig

npm 包在发布时使用的配置值。比如在安装依赖时指定了 registry 为 taobao 镜像源,但发布时希望在公网发布,就可以指定 publishConfig:

"publishConfig": {
"registry": "https://registry.npmjs.org/"
}

请参阅配置以查看可以覆盖的配置选项列表。

engines

peerDependencies

在 npm 版本 3 到 6 中,peerDependencies 不会自动安装,如果在依赖树中发现对等依赖项的无效版本,则会发出警告。从 npm v7 开始,默认安装peerDependencies

peerDependencies 的作用:

  • 版本一致性:确保多个包使用相同版本的依赖。例如,多个 React 组件库可能需要确保它们使用相同版本的 React。
  • 避免重复安装:防止在项目中安装多个版本的同一个依赖,从而减少包的体积和潜在的冲突。
  • 明确依赖关系:让使用你包的开发者明确知道需要安装哪些额外的依赖。

第三方配置

一些第三方库或应用在进行某些内部处理时会依赖这些字段,使用它们时需要安装对应的第三方库。

module

module字段是一个非官方的约定,用于指定一个包含ES6模块语法(即importexport语句)的入口点。这个字段主要用于构建工具和包管理器,以便它们可以在打包应用程序时优先使用ES模块版本的代码,这可能允许更好的摇树优化(tree-shaking)和其他模块化优势。

如下,main字段指向了一个CommonJS模块版本的入口点,而module字段指向了一个ES模块版本的入口点。当使用支持ES模块的工具(如Webpack、Rollup或其他现代JavaScript工具)时,这些工具可能会查找module字段以获取ES模块版本的代码。

{
"name": "my-es6-module",
"version": "1.0.0",
"main": "dist/my-es6-module.cjs.js",
"module": "dist/my-es6-module.esm.js"
}

请注意,module字段不是Node.js官方支持的字段,它是社区约定的一个扩展。因此,Node.js本身在运行代码时不会使用这个字段,它主要是为了打包和构建工具设计的。

该字段来自关于如何将 ECMAScript 模块集成到 Node 中的提案。因此,用于指定 包的ECMAScript 模块的文件路径。比如,如果您的包名为 foo,并且用户安装了它,然后执行 import {xxx} from 'foo,那么将返回module指定的文件的导出对象。

resolutions

package.json文件中,resolutions字段是一个Yarn特有的功能,它允许你覆盖依赖项的子依赖项的版本。这意味着你可以指定项目中使用的特定包的版本,即使这些包是作为其他包的依赖项安装的。这在解决版本冲突或强制使用某个修复版本的包时非常有用。

例如,如果你想要为一个子依赖项指定一个版本,你可以在package.json中这样写:

{
"resolutions": {
"some-sub-dependency": "1.2.3"
}
}

这将确保无论你的项目依赖树中的哪个包依赖some-sub-dependency,Yarn都会安装版本1.2.3。

请注意,resolutions字段是Yarn的一个特性,不是所有的包管理器都支持它。例如,npm就没有内置的等效功能。如果你使用的是npm,你可能需要使用其他工具或方法来解决依赖项版本的问题。

types typings

指定 TypeScript 的类型定义的入口文件

"types": "./es/index.d.ts",
"typings": "./es/index.d.ts",

unpkg

unpkg是一个快速的全球内容交付网络(CDN),它可以为任何在npm上发布的包提供文件。

package.json文件中,unpkg字段指定当用户通过unpkg CDN请求你的npm包时应该提供哪个文件,这通常是一个已经被转译和压缩的浏览器友好版本的文件,一般为UMD(Universal Module Definition)构建版本的文件。

例如:

{
"name": "your-package-name",
"version": "1.0.0",
"main": "index.js",
"unpkg": "dist/your-package.min.js"
}

在这个例子中,当用户通过unpkg CDN请求这个包时,CDN将提供位于dist/your-package.min.js的文件。这使得用户可以很容易地在网页中通过一个<script>标签直接引入这个包<script src="https://unpkg.com/your-package-name@1.0.0"></script> ,而不需要自己构建或打包。这个URL将会解析到你在package.json文件的unpkg字段中指定的文件。

如果没有指定unpkg字段,unpkg CDN默认会提供main字段指定的文件。

sideEffects

sideEffects不是npm官方的标准,是Webpack 官方推出的私有属性。Rollup 也适配了这个属性。sideEffects 除了能设置 boolean 值, 还可以设置为数组, 传递需要保留副作用的代码文件。

sideEffects字段是一个告诉打包工具(如Webpack)哪些模块是“有副作用”的。这个字段主要用于优化打包过程,如下表明包中的所有模块都没有副作用,因此打包工具可以自由地进行树摇(tree shaking),移除未使用的代码。

{
"name": "your-package",
"version": "1.0.0",
"sideEffects": false
}

实际项目中, 通常并不能简单的设置为 "sideEffects": false, 有些副作用是需要保留的, 比如引入样式文件。比如在项目中整体引入 Ant Design 组件库的 css 文件。

import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'

如果 Ant Design 的 package.json 里不设置 sideEffects,那么 webapck 构建打包时会认为这段代码只是引入了但并没有使用,可以 tree-shaking 剔除掉,最终导致产物缺少样式。

所以 Ant Design 在 package.json 里设置了如下的 sideEffects,来告知 webpack,这些文件具有副作用,引入后不能被删除。

"sideEffects": [
"dist/*",
"es/**/style/*",
"lib/**/style/*",
"*.less"
]

lint-staged

commitlint

exports

package.json 文件中,exports 字段用于定义包的导出路径,以便消费者可以通过不同的入口点导入包的不同部分。这个字段在 Node.js 和现代打包工具(如 Webpack 和 Rollup)中非常有用,因为它允许你更精细地控制包的导出结构。

exports 字段是一个对象,其中键是导出路径,值是导出路径的目标。你可以使用不同的条件来定义不同的导出路径,例如 requireimportnodedefault 等。

下面是一个示例,展示如何在 package.json 中使用 exports 字段:

{
"name": "my-package",
"version": "1.0.0",
"main": "index.js",
"exports": {
".": {
"import": "./esm/index.js",
"require": "./cjs/index.js"
},
"./feature": {
"import": "./esm/feature.js",
"require": "./cjs/feature.js"
},
"./package.json": "./package.json"
}
}
  • ".":表示包的主入口点。
    • "import":用于 ES 模块导入(import)。
    • "require":用于 CommonJS 模块导入(require)。
  • "./feature":表示包的一个子模块。
    • "import":用于 ES 模块导入(import)。
    • "require":用于 CommonJS 模块导入(require)。
  • "./package.json":允许消费者直接导入 package.json 文件。

假设你有以下文件结构:

my-package/
├── cjs/
│ ├── index.js
│ └── feature.js
├── esm/
│ ├── index.js
│ └── feature.js
└── package.json

在你的项目中,你可以这样导入 my-package

// 使用 ES 模块导入
import { mainFunction } from 'my-package';
import { featureFunction } from 'my-package/feature';

// 使用 CommonJS 模块导入
const { mainFunction } = require('my-package');
const { featureFunction } = require('my-package/feature');

你还可以使用条件导出来根据不同的环境导出不同的模块。例如,你可以为浏览器和 Node.js 环境定义不同的导出路径:

{
"name": "my-package",
"version": "1.0.0",
"main": "index.js",
"exports": {
".": {
"browser": "./dist/browser/index.js",
"node": "./dist/node/index.js",
"default": "./dist/index.js"
}
}
}

在这个示例中:

  • "browser":用于浏览器环境。
  • "node":用于 Node.js 环境。
  • "default":用于默认导出路径。

通过这种方式,你可以更精细地控制包的导出结构,以便在不同的环境中使用不同的模块。

prepublishOnly

prepublishOnlypackage.json 中的一个脚本钩子,它在 npm publishnpm install(仅当安装的是本地包时)命令运行之前执行。这个钩子非常适合用于在发布包之前执行一些必要的构建或验证步骤。

你可以在 package.json 文件的 scripts 字段中定义 prepublishOnly 脚本。例如:

{
"name": "my-package",
"version": "1.0.0",
"scripts": {
"build": "webpack --config webpack.config.js",
"test": "jest",
"prepublishOnly": "npm run build && npm test"
},
"devDependencies": {
"webpack": "^5.0.0",
"jest": "^26.0.0"
}
}

在这个示例中:

  • build:定义了一个构建脚本,使用 Webpack 进行构建。
  • test:定义了一个测试脚本,使用 Jest 进行测试。
  • prepublishOnly:在发布包之前运行构建和测试脚本。

什么时候运行 prepublishOnly:

  • npm publish:当你运行 npm publish 命令时,prepublishOnly 脚本会在发布包之前执行。
  • npm install:当你在本地安装包(例如 npm install ./path/to/package)时,prepublishOnly 脚本也会执行。

假设你有一个简单的项目结构:

my-package/
├── src/
│ └── index.js
├── dist/
│ └── index.js
├── package.json
└── webpack.config.js

你可以在 package.json 中定义 prepublishOnly 脚本,以确保在发布包之前进行构建和测试:

{
"name": "my-package",
"version": "1.0.0",
"scripts": {
"build": "webpack --config webpack.config.js",
"test": "jest",
"prepublishOnly": "npm run build && npm test"
},
"devDependencies": {
"webpack": "^5.0.0",
"jest": "^26.0.0"
}
}

当你运行 npm publish 命令时,以下步骤将依次执行:

  1. prepublishOnly:首先执行 prepublishOnly 脚本,即 npm run build && npm test
  2. 发布包:如果 prepublishOnly 脚本成功执行,包将被发布到 npm 注册表。

通过这种方式,你可以确保在发布包之前进行必要的构建和测试步骤,从而提高包的质量和可靠性。

使用package.json

const packageJson = require('./package.json')
const name = packageJson.name

· One min read

patch-package可以用来修改npm包的源码

  • npm install patch-package
  • package.json中增加postinstall
"scripts": {
"postinstall": "patch-package"
}
  • 修改依赖包的源码

  • 生成补丁,以element-ui为例,执行npx patch-package element-ui (注意,使用npx需要npm版本 > 5.2)

    生成的补丁(依赖包名+版本号.patch的文件)默认会在项目根目录自动创建的patches文件夹中

  • 注意:patch是锁定版本号的,如果升级了版本,patch内容将会失效,最好在package.json能够锁定版本号。

· 4 min read

JavaScript 语言在稳步发展。也会定期出现一些对语言的新提议,它们会被分析讨论,如果认为有价值,就会被加入到 https://tc39.github.io/ecma262/ 的列表中,然后被加到 规范 中。

查看语言特性的当前支持状态的一个很好的页面是 https://kangax.github.io/compat-table/es6/

如何让我们现代的代码在还不支持最新特性的旧引擎上工作?有两个工作可以做到这一点:

  • 转译器(Transpilers)
  • 垫片(Polyfills)

转译器(Transpilers)

  • 转译器 是一种可以将源码转译成另一种源码的特殊的软件。它可以解析(“阅读和理解”)现代代码,并使用旧的语法结构对其进行重写,进而使其也可以在旧的JavaScript引擎中工作。例如,在 ES2020 之前没有“空值合并运算符”。所以,如果访问者使用过时了的浏览器访问我们的网页,那么该浏览器可能就不明白 height = height ?? 100 这段代码的含义。转译器会分析我们的代码,并将 height ?? 100 重写为 (height !== undefined && height !== null) ? height : 100

  • 通常,开发者会在自己的计算机上运行转译器,然后将转译后的代码部署到服务器。

  • Babel 是最著名的转译器之一。

  • 现代项目构建系统,例如 webpack,提供了在每次代码更改时自动运行转译器的方法,因此很容易将代码转译集成到开发过程中。

垫片(Polyfills)

  • 新的语言特性可能不仅包括语法结构和运算符,还可能包括内建函数。例如,Math.trunc(n) 是一个“截断”数字小数部分的函数,例如 Math.trunc(1.23) 返回 1。在一些(非常过时的)JavaScript 引擎中没有 Math.trunc 函数,所以这样的代码会执行失败。

  • 对于新增函数这类的新特性,由于不是语法更改或者新增运算符,因此无需转译任何内容,而是需要声明缺失的函数,进而使其也可以在旧的JavaScript引擎中工作。

  • 更新/添加新函数的脚本被称为“polyfill”,它“填补”了空白并添加了缺失的实现。Math.trunc 的 polyfill 是一个实现它的脚本,如下所示:

    if (!Math.trunc) { // 如果没有这个函数
    // 实现它
    Math.trunc = function(number) {
    // Math.ceil 和 Math.floor 甚至存在于上古年代的 JavaScript 引擎中,所以在该polyfill中可以使用这俩函数
    return number < 0 ? Math.ceil(number) : Math.floor(number);
    };
    }
  • 两个有趣的 polyfill 库:

    • core js 支持了很多特性,允许只包含需要的特性。
    • polyfill.io 提供带有 polyfill 的脚本的服务,具体取决于特性和用户的浏览器。