组件库技术选型和开发环境搭建

发表于 1年以前  | 总阅读数:1047 次

前言

本文是 基于Vite+AntDesignVue打造业务组件库[4] 专栏第 2 篇文章【组件库技术选型和开发环境搭建】,为了让读者们沉浸式体验组件库开发,我将会手把手带着读者们搭建起一个组件库的 monorepo 开发环境,相关源码可在 vue-pro-components[5] 仓库中取得。

为什么选择 monorepo?

monorepo 这个词大家或多或少都听过,甚至已经在项目中应用过,问题来了,你能给 monorepo 下个定义吗?

别慌,我也不会,我们来看看维基百科给出的定义[6]。

In version control systems[7], a monorepo ("mono[8]" meaning 'single' and "repo" being short for '[repository](https://en.wikipedia.org/wiki/Repository_(version_control "repository") "Repository (version control)")') is a software development strategy where code for many projects is stored in the same repository.

可见,monorepo 的含义就是在一个单体仓库中管理多个项目,这种项目管理模式在一些大型项目中已经被广泛应用,比如 Vite[9], Vue[10], React[11], Angular[12], React Native[13], Jest[14], Pinia[15], Vue CLI[16], Element Plus[17], Modern.js[18], Next.js[19] 等。如果你打开这些项目仓库,你可以发现其中一个很明显的共性:它们都采用了packages目录来管理子包,每个子包中都包含一个package.json文件,也就是说子包也是一个独立的npm包。

进一步研究这些仓库时,我们可以发现,这些项目在支撑起整个 monorepo 体系时采用的技术方案是不一样的。

有的项目简单采用了 yarn workspaces,有的则使用了 Lerna,也有的用了 pnpm,还有的用了 Changesets,再卷一点的已经用上了 Turborepo。

Changesets 和 Turborepo 不能定义为 monorepo 方案,而是 monorepo 体系中强有力的配套工具。

鉴于笔者还未全面使用过以上所有方案,对于这些方案中的优缺点,无法给出客观的评价,读者们可以自行去查阅更多资料。

这里简单给个参考意见,帮助不了解这块的读者先有个粗略的认识,如有错误,还请评论指出:

yarn + workspaces

yarn 内置的 workspaces[20] 特性可以让子包之间的引用变得简单(其中也用到了 symbol link),在此基础上可以衍生出更多上层的能力,Lerna 就是在此基础上发展而来的工具。workspaces 支持了 monorepo 最基础的能力,但是仅靠它也显得有点单薄,因为它没有提供包的全生命周期管理能力。

Yarn workspaces aim to make working with monorepos[21] easy, solving one of the main use cases for yarn link in a more declarative way. In short, they allow multiple projects to live together in the same repository AND to cross-reference each other - any modification to one's source code being instantly applied to the others.

Lerna

Lerna[22] 可以解决上面说的问题,它提供了包的全生命周期管理能力,包括但不限于 新建子包 / 删除子包 / 管理子包依赖 / 发包 等等,并且有相关的命令行支持,能较大程度上提升 monorepo 项目开发和维护效率。除此之外,Lerna 团队还竭力提升性能和开发体验,具体见 Why Lerna?[23]

pnpm

pnpm[24] 从设计上就天然支持了 monorepo,同时还通过 严格的依赖结构 / symbol link / hard link 等能力解决了 幽灵依赖依赖占用大量存储空间 等问题。pnpm 也可以搭配 Lerna 使用。

Changesets

Changesets[25] 是 pnpm 推荐的一个致力于解决变更记录集、changelog、version 等问题的工具,据说比 Lerna Version 这块的处理更科学。它有一个生产和消费.changeset的过程,用户在一些复杂版本控制场景中有一定的自主控制权,因为你可以对 changeset 等内容做一定调整,自由度更高。

Turborepo

Turbo,涡轮增压嘛,这就是要起飞的节奏,Turborepo 内部的核心代码是基于 Go 来实现的,这跟 esbuild 一样,直接是降维打击啊!

简单看了一些 Turborepo[26] 官网的文档,可以发现 Turborepo是专注于提升构建性能的工具和平台,它在 Pipeline 编排、Output Caching、Remote Caching、Output Replaying 等方面做了很多努力,同样的事情不做第二次,这与 Lerna 现在的管理团队 Nrwl 研发的构建平台 Nx[27] 的发力方向有点相似。

合理的 Pipeline 编排可以最大限度发挥 CPU 性能。缓存用好了真的是一把利刃,对于重复的工作,得到秒级甚至毫秒级的响应是真的香,这在 monorepo 项目中尤其重要,因为你不知道一个 monorepo 可能会演变成多大的工程!而且 Remote Caching 在 CI/CD 中也能发挥很大作用!

为什么这些明星项目都不约而同选择了 monorepo 呢?背后的原因可能有这些:

  • 现代前端工程的复杂度在不断提升,使得拆包成为了必然趋势
  • 但是把一个大型项目拆成多个仓库又让管理和联调变得十分困难,npm link之类的方案开发体验太差。
  • 目前最佳的方案还是在一个仓库维护,然后通过技术手段改善单体仓库的劣势,既能保持子包之间的独立性,又能让包之间联调变得简单
  • 使得集成化的 CI/CD 变得更加便捷。
  • 更多亮点值得探索......

技术选型

在组件库的技术选型这块没有太多可说的,基本上是围绕项目的需求和自身的能力展开,按照开发过程中的实际需求引入相关的技术方案。这中间会存在主观意愿,仅供参考!

  • Monorepo: 我还是选择了保守一点的 Lerna,这个我相对熟悉一点,同时也是想多踩踩坑,知道坑在哪里,才能明白为什么要换更好的工具。
  • 前端框架:如专栏标题所述,我选择了个人更熟悉的 Vue3 生态。
  • 类型支持: TypeScript。
  • 基础 UI 组件库:AntDesignVue,继承了 AntDesign 的企业级设计风格,个人感觉 AntDesignVue 相对其他 Vue 生态的组件库更有质感,但是它也不是完美的。
  • 构建工具:Vite, Rollup, Gulp 以及相关插件生态。组件库建设是一个相对复杂的工程,很难依靠一种工具把所有事宜处理完毕,所以整合工具链是必要的。
  • CSS预处理器:Less。选择 Less 主要是考虑后续切换主题,这块 Less 比较好处理(纯属个人主观意见,毕竟还有不依赖 preprocessor 的)。
  • 发布流程工具:release-it。
  • CI/CD: Github Actions。这个没有强制要求,有很多选择。
  • 规范/约束之类的:ESLint, Prettier, StyleLint, husky, commitizen 等等。
  • 更多......

开发环境搭建

说太多概念也不太容易消化,我们来实操一下。

创建 Lerna 工程

首先我们需要新建并进入vue-pro-components工程目录,接着通过npx lerna init创建一个工程。

$ mkdir vue-pro-components && cd vue-pro-components
$ npx lerna init
lerna notice cli v4.0.0
lerna info Initializing Git repository
lerna info Creating package.json
lerna info Creating lerna.json
lerna info Creating packages directory
lerna success Initialized Lerna files

可以发现 Lerna 为我们生成了一个 monorepo 项目的基本骨架:

$ tree
.
|-- lerna.json
|-- package.json
`-- packages

package.json

粗略看一下,package.json中的private字段设置为了true

{
  "name": "root",
  "private": true,
  "devDependencies": {
    "lerna": "^4.0.0"
  }
}

这代表什么意思呢?我们看看 npm 文档中关于 private[28] 的描述。

If you set "private": true in your package.json, then npm will refuse to publish it.

private设置为true时,就代表你不需要在npm公开发布这个包。看到这,有的读者可能会纳闷了,“这好像有点问题吧,组件库一般是要发布的呀!”

不用慌,由于我们采用的是 monorepo 架构,具体发布的组件库其实是packages目录下的一个子包。而整个工程的主包则是用来组织起整个大框架,不发布到npm也是可以理解的。

同时,这也符合 Yarn 1.X 版本的强制要求[29],如果需要用到workspaces特性,必须声明privatetrue。虽然 Yarn Modern Version[30] 已经取消了这个限制,但是迟迟没有作为 Yarn 的默认安装版本,在升级迁移[31]这块还有不少阻力。

lena.json

我们再观察一下lerna.json这个文件,它通过packages字段约定了子包都分布在哪些目录下,这里支持 glob pattern 匹配,也可以是一个 package 的 path。

{
  "packages": [
    "packages/*"
  ],
  "version": "0.0.0"
}

对于version字段,Lerna 提供了两种版本策略[32]供我们选择,我们应该怎么选择呢?这里先不展开说,免得大家产生太多疑问导致不必要的焦虑。

工程搭建完毕后,我们先与 remote 仓库(您需要保证远程仓库存在)关联一下,方便后续提交代码。如果您已经 fork 该仓库,请将仓库地址改成您自己的。

git remote add origin https://github.com/cumt-robin/vue-pro-components.git

新建组件库子包

有了上面的基本框架,我们可以着手新建一个组件库子包,这个包将存放组件相关源码,这里用到了lerna create命令。我们可以根据交互提示填上一些必要的信息,先把子包建好,一些信息可以后续再更改,不必过于纠结。

$ lerna create vue-pro-components
// 在一步步提示下,先将一个npm子包搭建起来
package name: (vue-pro-components)
version: (0.0.0)
description: pro components based on vue3
keywords: components,vue3,vite,typescript,unplugin,on demand,pro
homepage:
license: (ISC) MIT
entry point: (lib/vue-pro-components.js) index.js
git repository:

注意,我这里用到的 package name 是 vue-pro-components,这个 name 也将作为我要发布到 npm 上的包名。

也不用担心这个包名 vue-pro-components 和整个工程的目录名相同,因为主工程是不会发布到 npm 的。

这里先不急着加具体内容,因为我们需要先把大的框架理清楚,继续往下看。

新建 playground 子包

playground 翻译过来就是游乐场,这个子包可以作为我们调试组件表现的地方,这里直接选择用 Vite 初始化一个工程。

我们尝试一下不使用lerna create命令新建 package。

cd packages && yarn create vite playground --template vue-ts

用 Vite 创建的这个 playground 包默认也是 private 的,playground 本来的作用就是调试或展示组件的基本效果,可以打包后作为一个 web 应用发布到公网,但是不需要发布到 npm,所以设置为 private 符合预期。

我该用哪种 version 策略?

回到上文留下的疑问,两种版本策略,我们该怎么选?

1 . Fixed/Locked mode (default)[33]

Fixed mode 意味着version字段对应着具体的版本号,比如0.1.0。在这种模式下,各个子包的版本号相对集中,一般来说可以理解为同一个版本号(也有例外),Lerna 会在执行lerna version命令时根据用户的选择自动更新version字段,同时会修改发生过代码变更的子包的package.json中的version字段。

我们可以来试验一下,先把代码 commit & push 到远程,这里我用了一个新分支c1

// 回到根目录
git checkout -b c1
git add .
git commit -m 'chore: 先将代码提交到远程,方便后续测试lerna version'
git push --set-upstream origin c1

文档中提到,如果当前 major 版本号是 0,则认为所有变更都是破坏性的,这意味着修改任何一个包中的内容,lerna version都会更新所有子包的版本号。我们来试试,修改其中一个子包vue-pro-components的内容,在index.js加了一行注释,然后 commit,接着使用lerna version更新版本号。

$ git add .
$ git commit -m 'chore: 测试 major 版本号为 0 时修改一个包'
$ lerna version
lerna notice cli v5.3.0
lerna info current version 0.0.0
lerna info Assuming all packages changed
? Select a new version (currently 0.0.0) (Use arrow keys)
> Patch (0.0.1)
  Minor (0.1.0)
  Major (1.0.0)
  Prepatch (0.0.1-alpha.0)
  Preminor (0.1.0-alpha.0)
  Premajor (1.0.0-alpha.0)
  Custom Prerelease
  Custom Version

当我们选择 Patch 更新后,可以看到,两个子包的版本号都变成了 0.0.1,并且lerna.json中的version也变成了0.0.1

Changes:
 - playground: 0.0.0 => 0.0.1 (private)
 - vue-pro-components: 0.0.0 => 0.0.1

我们再试试加一行注释,模拟把一个包的大版本号变成 1 的场景,可以看到两个包的版本号以及lerna.json中的version也变成了1.0.0

Changes:
 - playground: 0.0.1 => 1.0.0 (private)
 - vue-pro-components: 0.0.1 => 1.0.0

此时,我们再加一行注释,模拟引入一个 feature,再发起 minor 位的版本号变更,会发现仅有一个包的version变成了1.1.0,同时lerna.json中的version也变成1.1.0,而另一个包的版本号没有变化,这看起来还比较合理,因为我们认为主版本号 1 以上的是相对稳定的版本,按需更新版本号是比较合理的。

Changes:
 - vue-pro-components: 1.0.0 => 1.1.0

接着,我们把两个包都改一点内容再测试一次。

Changes:
 - playground: 1.0.0 => 1.1.1 (private)
 - vue-pro-components: 1.1.0 => 1.1.1

做了这些尝试我们可以发现,lerna version做版本变更时,只会让我们选择一次版本,这一次选择将作用到多个包上。

假设某次更新版本时,我希望一个包是 minor 更新,另一个包是 patch 更新,该怎么办呢?我们继续往下看。

2 . Independent mode[34]

Independent Mode 就是采用独立的版本号控制,会在执行lerna version命令时逐个询问各个 package 的新版本号,我们可以通过修改lerna.json中的version字段值为independent打开这个模式。

当我只修改其中一个包,lerna version会提示我选择一个版本号,这个版本号也将只作用到这个包上,其他的包不受影响。

$ lerna version
lerna notice cli v5.3.0
lerna info versioning independent
lerna info Looking for changed packages since v2.0.0
? Select a new version for vue-pro-components (currently 2.0.0) Patch (2.0.1)

Changes:
 - vue-pro-components: 2.0.0 => 2.0.1

接着我们修改两个包的内容再测试一次,Lerna 会让我们单独为每个包选择新的版本号。

$ lerna version
lerna notice cli v5.3.0
lerna info versioning independent
lerna info Looking for changed packages since vue-pro-components@3.0.0
? Select a new version for playground (currently 2.0.0) Minor (2.1.0)
? Select a new version for vue-pro-components (currently 3.0.0) Minor (3.1.0)

Changes:
 - playground: 2.0.0 => 2.1.0 (private)
 - vue-pro-components: 3.0.0 => 3.1.0

也就是说,Independent Mode 下,版本号是各管各的,按需选择

简单总结一下:在 Fixed Mode 下,lerna.json 中记录了各个包中最新的版本号。如果当前大版本号是 0,则修改任意一个包中的内容都会引起所有包的版本号更新;反之,仅更新变动的包的版本号。还有一个场景,就是继续选择大版本的更新,也会引起所有包的版本号更新。总的来说,Fixed Mode 下,版本号捆绑性还是很强的。而在 Independent Mode 下,各个包的版本号相对独立,需要开发者结合包的修改情况来手动选择各个包的版本号。

个人建议:如果你的整个 monorepo 项目中各个子包联系性非常紧密,目标是对外提供统一的服务,那么 Fixed Mode 是一个不错的选择,例如 Vue CLI,就是采用了 Fixed Mode。对用户来说,他享受的是整个 Vue CLI x.x.x 版本带来的能力,而不太关心 @vue/cli-ui@vue/cli-service 现在是哪个版本。如果你的 monorepo 项目中各个子包联系性稍弱,对外提供多种能力(比如 Lint 配置、Utils 工具、通用 Hooks、UI 库等等),那选择 Independent Mode 则是一个不错的选择,这种做法常见于企业内部,通常 monorepo 是作为整合多种能力的一个重要工具,既能在各个子包之间实现一部分复用,又能单独对外提供输出能力。当然,任何事情都不是一成不变的,如果你对版本控制欲很强,也可以果断选择 Independent Mode。

我这里选择的是 Independent Mode。

子包之间的引用

对版本策略有个粗略的认识后,我们给子包之间建立一点联系,感受一下 monorepo 最大的魅力。

我们先在vue-pro-components子包写一个简单的组件Icon,无需真正实现图标组件,仅仅用来测试一下。

<template>
    <i>{{ icon }}</i>
</template>

<script>
export default {
    props: {
        icon: {
            type: String,
            default: '默认图标'
        }
    }
}
</script>

一个粗略的目录结构大概是这样的:

由于 Vue3 组件需要用到框架依赖,我们需要在package.json中声明一个peerDependencies

"peerDependencies": {
    "vue": "^3.2.0"
}

然后在项目根目录的package.json中加一个统一安装依赖的脚本。

"scripts": {
    "bootstrap": "lerna bootstrap -- --hoist"
}

接着执行这个bootstrap命令,

yarn bootstrap 

我们可以发现,在根目录中出现了node_modules目录,而在各个子包中没有出现node_modules,这是--hoist在起作用,将依赖提升到了根目录,可以节省一部分空间。

我们还注意到,vue-pro-componentsplayground两个包也出现在了node_modules目录中,实际上它们是软链接,链接的源目录是packages目录中对应的子包目录,这样的目录结构符合 Node 的模块加载策略,于是子包之间就可以像使用一个普通的 npm 包一样互相引用了。

软链接就是 symbolic link,类似于 Windows 系统中快捷方式的概念。但是在 Windows 系统中, workspace 的具体实现并不是快捷方式,而是采用了 junction。

lerna bootstrap不仅为各个 package 安装了自身的依赖,还将各个 package 以 symlink 的方式安装到了node_modules中,让其他 package 拥有了引用自己的能力。

接着我们试着在playground子包中引用一下vue-pro-components子包的组件 Icon

1 . 首先需要将vue-pro-components作为playground子包的一个依赖。

lerna add vue-pro-components --scope=playground

2 . import 引入组件并使用。

// 1. script 中引入 Icon 组件
import { Icon } from "vue-pro-components"

// 2. template 中使用组件
<Icon icon="icon-up"></Icon>
<br>
<Icon icon="icon-down"></Icon>

3 . 预览效果。这需要把 playground 这个子包的开发环境跑起来,也就是要执行它的dev脚本。为了方便起见,我们可以在项目根目录的package.json中加一个playground:dev脚本,这里用到lerna run,它可以根据scope选项执行某个子包的脚本。

"scripts": {
  "bootstrap": "lerna bootstrap -- --hoist",
  // 加入这条脚本
  "playground:dev": "lerna run --scope playground dev"
}

这样,我们就可以直接在根目录直接跑 playground 的开发环境了。虽然 Icon 组件还没什么太多的内容,但是我们可以看到,playground 子包已经可以顺利引用 vue-pro-components 子包的组件了。

gif 太大,给个链接吧:https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f3f819d4665440b3a3640840ae66142c~tplv-k3u1fbpfcp-watermark.image?

简单尝试发布到 npm

整个组件库的工程配置一股脑说完,也是很难吸收的,我们先来点简单的,也是最重要的一步,把组件库先发布到 npm 上。

首先你需要有一个 npm 账户[35]。

有了账号后,可以来到你的项目工程目录下,通过终端登录 npm,可以输入npm adduser或者npm login进行登录。

npm adduser

如果登录失败,考虑你的 registry 是不是正确,如果用了国内的 npm 代理,建议登录时带上--registry=https://registry.npmjs.org/参数。

登录成功后,就可以试着发布你的 npm 包了。npm publish 可以发布包,但是在 lerna 项目中,我们可以用 lerna publish代替。

通常,我们会在项目中通过.npmrc或者.yarnrc配置一个国内的 registry 代理,加快安装依赖的速度。但是在发包的时候,我们还是要发布到 npm 官方的 registry 中,所以就需要给 lerna publish 配置一个 registry 参数,告诉 lerna publish 发布到哪个 registry 中。

我们修改一下lerna.json

同时,还有一个地方需要修改,那就是vue-pro-components子包的package.json,需要将其publishConfig.access字段设置为"public"

从上图我们可以知道,如果一个包是 scoped package,也就是带命名空间的包,例如它的包名是@vue-pro-components/utils,对于这样的包,如果不设置access"public",是不能公开发布和安装的。虽然我们发布的这个 vue-pro-components 不是 scoped package,但是为了养成一个好习惯,我们还是给它设置一下access

接着,我们在根目录package.json中增加一个脚本,方便我们进行发布操作。

lerna publish from-package --yes

我们试着执行这个publish:package脚本,如果能看到下面这样的信息,就表示发布成功了。

gif太大,给个链接:https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3adbb28a06f04565ab37b345471d56a3~tplv-k3u1fbpfcp-watermark.image?

结语

截至到目前,我们只是在组件库开发环境搭建上做了一些粗略的尝试,对一些关键节点做了验证,整个项目还是处于一个非常简陋的状态,但是读者们也不必担心内容的丰富度,随着专栏后续内容的深入,一些工程化配置(包括 TypeScript)也会慢慢完善起来。如果您对我的专栏感兴趣,欢迎您订阅关注本专栏[36],接下来可以一同探讨和交流组件库开发过程中遇到的问题。

参考

[1]基于Vite打造业务组件库(开篇介绍): https://juejin.cn/post/7146022961894391821

[2]实战案例:初探工程配置 & 图标组件热身: https://juejin.cn/post/7160549169566842893

[3]vue-pro-components c1 分支: https://github.com/cumt-robin/vue-pro-components/tree/c1

[4]基于Vite+AntDesignVue打造业务组件库: https://juejin.cn/column/7140103979697963045

[5]vue-pro-components: https://github.com/cumt-robin/vue-pro-components

[6]维基百科给出的定义: https://en.wikipedia.org/wiki/Monorepo

[7]Version control: https://en.wikipedia.org/wiki/Version_control

[8]wikt:mono-: https://en.wiktionary.org/wiki/mono-#English

[9]Vite: https://github.com/vitejs/vite

[10]Vue: https://github.com/vuejs/core

[11]React: https://github.com/facebook/react

[12]Angular: https://github.com/angular/angular

[13]React Native: https://github.com/facebook/react-native

[14]Jest: https://github.com/facebook/jest

[15]Pinia: https://github.com/vuejs/pinia

[16]Vue CLI: https://github.com/vuejs/vue-cli

[17]Element Plus: https://github.com/element-plus/element-plus

[18]Modern.js: https://github.com/modern-js-dev/modern.js

[19]Next.js: https://github.com/vercel/next.js

[20]workspaces: https://yarnpkg.com/features/workspaces

[21]monorepos: https://yarnpkg.com/advanced/lexicon#monorepository

[22]Lerna: https://lerna.js.org/

[23]Why Lerna?: https://lerna.js.org/docs/introduction#why-lerna

[24]pnpm: https://pnpm.io/

[25]Changesets: https://github.com/changesets/changesets

[26]Turborepo: https://turborepo.org/

[27]Nx: https://nx.dev/

[28]private: https://docs.npmjs.com/cli/v8/configuring-npm/package-json#private

[29]Yarn 1.X 版本的强制要求: https://classic.yarnpkg.com/en/docs/workspaces

[30]Yarn Modern Version: https://yarnpkg.com/features/workspaces

[31]升级迁移: https://yarnpkg.com/getting-started/migration

[32]两种版本策略: https://lerna.js.org/docs/features/version-and-publish#versioning-strategies

[33]Fixed/Locked mode (default): https://lerna.js.org/docs/features/version-and-publish#fixedlocked-mode-default

[34]Independent mode: https://lerna.js.org/docs/features/version-and-publish#independent-mode

[35]npm 账户: https://www.npmjs.com/signup

[36]订阅关注本专栏: https://juejin.cn/column/7140103979697963045

[37]laobaife: https://qncdn.wbjiang.cn/%E5%BE%AE%E4%BF%A1%E4%BA%8C%E7%BB%B4%E7%A0%81%E5%90%8D%E7%89%87.jpg

[38]vue-pro-components c1 分支: https://github.com/cumt-robin/vue-pro-components/tree/c1

[39]实战案例:初探工程配置 & 图标组件热身: https://juejin.cn/post/7160549169566842893

END

本文由哈喽比特于1年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/-Fc1FyWkm-cAV58zirgpiQ

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:7月以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:7月以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:7月以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:7月以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:7月以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:7月以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:7月以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:7月以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:7月以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:7月以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:7月以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:7月以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:7月以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:7月以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:7月以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:7月以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:7月以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:7月以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:7月以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:7月以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  236876次阅读
vscode超好用的代码书签插件Bookmarks 1年以前  |  6889次阅读
 目录