渐进式 Unbundled 开发工具探索之路

发表于 3年以前  | 总阅读数:243 次

简短摘要:得益于现代浏览器内置了模块处理系统(ESM), 业界新兴开发工具 Snowpack、WMR、Vite 等直接将模块解析加载过程直接交给浏览器, Dev Server 能够秒级启动。和传统开发工具编译时解析加载模块最终打包到 JS Bundle 中相比,本地开发体验提升明显

传统 Bundled Development

复杂项目构建太慢

业界主流的开发工具还是以 Webpack 为主,随着项目体积增大,开发阶段一次性将源代码和第三方依赖编译处理打包到一起的耗时会显著增加。在我们团队内部的 monorepo 仓库中,应用项目开发时,为了开发阶段调试方便,通常也会对一些公共库源码一起打包编译,成千上万个模块导致首次 dev server 启动耗时在几分钟甚至十几分钟,严重影响了开发效率与体验。

Webpack 打包慢的问题相信也是大家都会遇到的问题。随手一搜,各种 Webpack 配置优化以及最佳实践之类的文档数不胜数。大部分也都是遵循 Webpack[1]Build Performance Guide[2]。

粗略一看上面的一些优化方式很多, 但是在我们的场景中很多都是不够通用,比如 thread-loader 结合 babel-loader 的方式在业务项目中经常会遇到报错的情况,原因是业务项目通常会使用 babel-plugin-import 针对业务内部的组件库按需加载组件以及样式,配置大致如下:

[  
  "babel-plugin-import",  
    {  
      "libraryName": "custom-ui-components",  
      "style": (name: string, file: Object) => {  
        return `${name}/style/2x`;  
      }  
    }  
]

我们知道 JavaScript 中线程间共享的数据必须序列化,上述style函数在序列化时会直接报错。

esbuild 作为一个 bundle 工具性能很不错,但是针对应用生产环境打包还存在一些问题,如降级到 ES5,Code Split 、 CSS 处理等。社区内有提供替换 babel-loader 的 esbuild-loader, 通过 loader 的方式在 Webpack JS 运行时中编译单个文件的方式在速度上也不如单纯用 esbuild 一把梭快。对浏览器兼容性有要求的项目,平滑使用也比较困难。

减少处理的模块数量方面,针对 MPA,简单的做法是在 dev 时显式指定需要开发的页面,但是比较局限不够灵活, Webpack 5 提供的实验性特性 Lazy Compilation 在开发阶段能够做到真正的按需编译提升 dev server 启动速度:

首次 dev server 启动时, 会代理 Webpack 入口以及 dynamic import 导出的模块,打开浏览器页面后,代理模块在运行时通过 Server-Send-Events 与 Lazy Compilation Backend Server 通信决定需要真正编译处理的资源。但是作为实验功能,目前还不是很稳定,笔者在使用时,遇到过初次打开页面白屏必须手动刷新的问题。而且后续对需要编译的入口通过 babel-loader 或者 ts-loader 重新编译打包时,仍然会有慢的问题存在。

Webpack 4 中通过插件lazy-compile-webpack-plugin[3]也可以实现类似的效果。

更多的优化方式这里不一一列举, 总结下来,现有的一些 Webpack 打包优化方式或多或少都不够通用,或者存在一些问题。

打包工具之上的探索

沿着减少 Webpack 处理模块数量的思路,node_modules 下的第三方依赖如果能够从打包环节剔除,仅对业务代码打包,对构建速度肯定会有明显的提升。

比较常见的方法是将常用的第三方库在 Webpack 构建时配置 external, Html 中直接通过 script 标签引入 UMD 产物, 这种方式有以下问题:

  1. 每个依赖的 UMD 产物会增加额外的一段兼容代码,造成冗余。
  2. 浏览器中直接使用可能会污染全局变量,以及容易被修改覆盖。
  3. 很多公司内部包,并没有提供 UMD 产物。

既然 UMD 产物不太符合我们的场景,那么直接替换依赖为对应的 ESM 产物呢?业界也有类似的思路:

1.Rollup 社区有rollup-plugin-cdn支持代码中从 unpkg 引入依赖的 ESM 产物:

import hyper from 'https://unpkg.com/hyperhtml@latest/esm/index.js';  
hyper(document.body)`  
  <h1>Hello ESM</h1>`;  

2 .Pika(Skypack 前身)提供了\@pika/cdn-webpack-plugin支持生产环境构建时将 package.json 中的依赖替换为 Pika CDN 上对应的链接,同时 html 中通过script type=module加载打包后的 js 产物, 以 React 为例在最终 JS Chunk 中大致如下:

import __mun2tz2a_default, * as __mun2tz2a_all from "https://cdn.skypack.dev/react";  
    window["https://cdn.skypack.dev/react"] = Object.assign((__mun2tz2a_default || {}), __mun2tz2a_all);  
(window["webpackJsonptask_activity"] = window["webpackJsonptask_activity"] || []).push([["vendors"],{  
 /***/ "50ab":  
/*!****************************************!*\  
  !*** ./node_modules/__pika__/react.js ***!  
  \****************************************/  
/*! no static exports found */  
/***/ (function(module, exports) {  
module.exports = window["https://cdn.skypack.dev/react"];  
/***/ }),  
}])  

可以看到利用浏览器对 ESM 的原生支持,直接从 Skypack CDN import 导入 React ,之后以全局变量的方式挂到 window 变量上。其他模块中导入 React ,最终会是 window 上存在的变量。

考虑到我们主要是想提升 dev server 启动时构建的速度,并且很多依赖都是公司内部包,笔者在\@pika/cdn-webpack-plugin[4]的基础上,结合团队内部的 CJS 转 ESM 服务,在 dev 环节将用到的第三方依赖改成从线上 import 导入。最终在实际业务项目中测试效果并不理想,主要有以下一些问题:

  1. 第三方依赖以及依赖的依赖都会直接在浏览器中请求,请求数量成指数增长,浏览器中白屏时间过长,甚至请求数量会直接爆炸,运行报错。
  2. 速度上面,一些项目确实能够在 6s 左右 dev 完成,但是在一些比较大的内部 monorepo 中,仍然是需要几十秒的时间。
  3. CJS 转 ESM 中间的坑太多: 大部分依赖都还是只提供了 CJS 版本,在转换过程中不论是用 rollup-plugin-commonjs 还是 esbuild ,一些问题都避免不了。
  4. 同样会污染全局变量。

在 Webpack 生态基础上将第三方依赖以 ESM 形式直接加载看起来也不太能满足我们的场景,那么如何更好地提升 dev server 启动速度呢?

迈入 Unbundled Development

业界现状

基于 ESM 的现代 unbundled 开发工具在社区如雨后春笋不断发展,es-dev-server、Snowpack 、Wmr 、Vite 等工具直接直接抛弃 Webpack,通过内部的 Dev Server 接收请求后实时对 JS、TS、CSS 等资源实时编译处理。

图片来自 Snowpack 官网: https://www.snowpack.dev/concepts/how-snowpack-works

和 Webpack 等打包工具相比,这类的 unbundled 开发工具有如下优点:

  1. 飞快的启动速度:dev server 启动时仅需要对依赖预处理编译成 ESM 格式,一次处理之后,后续依赖没有变化时,可以做到秒级启动,
  2. 实时按需编译:运行时浏览器第一次请求对应模块时,dev server 本地实时编译处理返回对应内容。
  3. 更快的热更新:针对具体修改的文件,根据模块的依赖关系图, 逐步向上寻找 accept 该模块 HMR 更新的文件,重新请求文件内容。和 Webpack 的热更新需要重新整体构建相比会更快。

这种新兴 Unbundled Development 模式看着能够满足我们对 dev server 启动速度的需求,下面的问题就是针对使用我们内部应用开发工具的业务项目来说如何平滑的接入这些工具。

由于我们的应用开发工具提供了一套现代 Web 项目开发范式,从应用入口和各种资源的处理使用,以及服务端 API 的一体化调用上都有内部一些标准。直接在项目中使用上述工具会有很多问题,免不了对上面的工具进行二次开发,这就要求这些工具提供足够灵活的扩展自定义方式,这里就业界用的比较多的 Snowpack 和 Vite 2.0 简单对比如下: (点击查看大图)通过上面的简单对比,以及文档丰富程度上来看, Vite 2.0 扩展起来会更加灵活方便。因此在给我们的应用开发工具提供 Unbundled Development 模式前期,也是果断选择了 Vite 2.0 作为底层, 但是最终实现版本里面我们选择借鉴 Vite、Wmr 等工具自主开发实现 dev server 部分,主要有以下几个角度的考虑:

  1. 依赖预处理过程需要深度定制:一些公司内部包需要特殊处理,这部分我们最终决定放到内部的 CJS 转 ESM 服务上,同一个 package 的具体版本,只会处理一次,后续使用时直接下载转换后的产物即可。
  2. 深度定制需求:在我们的设计体系里面,用户并不会直接接触到具体底层工具的配置,比如 babel.config.js、postcss.config.js 等,而是集中在我们提供的配置文件进行自定义的需求。Vite 2.0 本身是支持这些文件的加载,另一方面具体资源文件处理的标准也有不同的地方,比如 CSS Modules 处理上,我们默认支持文件后缀.module.css的形式,也支持关闭文件后缀的约定。这些有的可以通过配置实现,但是大部分还是要接管 Vite 内部的资源的编译处理过程,如果通过 Vite 提供的插件可以完成,这样对 Vite 利用不是很充分,也显得比较冗余。
  3. 后续维护与发展:初期我们打算提供基本的 dev server 解决开发环节慢的问题,后期需要结合已有 SSR、SSG 等建设补齐对应的能力。

综上,实现 Unbundled Dev Server 对我们来说更容易维护以及后续添加一些能力更方便。

Unbundled Dev Server 原理

为了更好的理解 Unbudled 开发工具的细节,我们从下面几个方面分别介绍:

依赖预处理

上文我们提到,业务项目中使用到的依赖很多只提供了 CJS 产物, 首先,我们需要将第三方依赖转换成 ESM 格式。业界常用的工具主要是 Rollup 和 esbuild 等构建工具。

基本思路是分析项目源码中使用到的依赖, 这些依赖作为构建工具的入口整体打包,好处是整体将依赖打包得到 common chunks,浏览器中打开页面加载第三方依赖的请求数量会少很多。缺点是添加依赖或者删除一些依赖改动了 package.json 或者 lock 文件时, 需要重新对依赖编译打包,在一些比较大的中后台项目中,依赖预处理耗时还是存在的。

这里我们目前采用的方案是,沿用之前内部已有的 CJS 转 ESM 服务,直接下载线上依赖已经转换好的的 ESM 产物。后续针对下载的 ESM 文件,用 esbuild 做一次 bundle 减少浏览器中运行的请求数量。

借助 CJS 转ESM 服务和直接本地编译转换相比,有以下好处:

  1. 首次对项目依赖预处理之后,后续添加依赖只需要从云端下载新添加的依赖 ESM 产物,之后借助 esbuild 重新 bundle 耗时也不会很多。
  2. 一些需要特殊处理的第三方依赖,统一在云端处理修复,业务项目不依赖开发工具的发版升级。针对一些通用的处理场景,我们会提供 UI 界面引导用户输入依赖对应信息,自动修复。
  3. CJS 到 ESM 转换的产物可以在本地全局缓存,跨项目复用已经编译好的产物, 也就是说,随着使用项目增加,云端和本地双重缓存级联,能够大幅度减少 CJS 转 ESM 的时间。

同时我们针对内部模块比较多的依赖,如 antd,在线上 CJS 转 ESM 时,会将内部模块打包到单个产物中,这样能减少成百上千的网络请求。以 React 为例, 直接从云端下载的 ESM 产物内容截图如下:

可以看到依赖项 object-assign 会额外带有版本号信息。在递归下载第三方依赖 ESM 文件后,能够得到如下的 json 文件,存储某个版本依赖实际 ESM 文件的路径, 如下:

{  
   "react?16.14.0": "/Library/Caches/__web_modules__/react@16.14.0.js",  
   "react-dom?16.14.0": "/Library/Caches/__web_modules__/react-dom@16.14.0.js",  
   "object-assign?4.1.1": "/Library/Caches/__web_modules__/object-assign@4.1.1.js",  
}  

版本号是直接在 node_modules 中解析对应依赖位置获取的,也就是说,项目下存在某个依赖多个版本也是支持的。

之后通过 esbuild 打包时借助 onResolve hook 从上面的 json 文件中匹配具体的 ESM 文件路径, 示例代码如下:

const bundleResult = await require('esbuild').build({  
    entryPoints: ['react', 'react-dom'],  
    bundle: true,  
    splitting: true,  
    chunkNames: 'chunks/[name]-[hash]',  
    metafile: true,  
    outdir: webModulesDir,  
    format: 'esm',  
    treeShaking: 'ignore-annotations',  
    plugins: [  
      {  
         name: 'resolve-deps-plugin',  
         setup(build) {  
            build.onResolve({filter: /^/}, async args => {  
               const { kind, path } = args;  
               if (['import-statement', 'entry-point', 'dynamic-import'].includes(kind)) {  
                 if (kind === 'entrypoint') {  
                   //  针对 bundle 入口, 直接本地 resolve 得到版本号  
                   // 在上面的 json 文件中拿到具体路径返回  
                 } else if (path.startsWith('/esm/bv')) {  
                   // 针对依赖的依赖,比如 object-assign^4.1.1  
                   // 通过 semver 在文件中匹配获取实际的 ESM 文件路径返回  
                 }  
               }  
            })  
         }  
      }  
    ]  
})  

到这里,依赖预处理已经完成了,最终通过bundleResult.metafile能够得到我们最终的 import-map.json 后续在请求模块时用来解析模块依赖路径到转换后的 esm 文件, 目录结构和内容大致如下:

针对 monorepo 中某些 package 并不发布,在应用中直接使用源码统一构建的场景, 在分析使用到的依赖时,也会收集这些 package 用到的依赖,统一预处理成 ESM 格式。某些 package build 后提供产物在应用中使用时,会根据当前 package 最新代码, 本地实时编译转换成 ESM,这里本地编译转换和云端会复用底层代码,效果上也类似。

资源文件处理

整体 Server 的实现部分借鉴了 WMR 和 Vite 的 插件系统设计, Plugin 作为 Rollup Plugin 的超集,通过 Plugin Container 提供统一的插件接口, 和 Snowpack、es-dev-server 在 Server 中间件中处理请求、文件转换不同,WMR 、Vite 的插件体系将文件转换以及 Server 中间件分离开来,概念上比较清晰, 也比较易于维护。WMR、Vite 这种插件系统也有利于 dev 和 build 时复用文件转换相关的逻辑。

从浏览器发出请求到 Server 返回对应资源的流程如下图所示:

在 resolveId hook 中根据 url 解析出具体文件路径。load hook 主要加载文件内容。transform hook 是编译转换各种类型资源文件的核心。下面对几种资源文件在 Server 内部的处理展开描述:

JSX/TSX 编译转换

我们知道 JSX或 TSX 不能直接在浏览器中运行,这里因为 dev 环节对浏览器兼容性没有要求以及追求更快的实时编译速度,直接使用 esbuild transform 即可:

const result = await esbuild.transform(code, {  
  loader: 'tsx',  
  sourcefile: importer,  
  sourcemap: true,  
  target: 'chrome63'  
})  

在业务项目中实践时,遇到的一些问题举例如下:

  1. esbuild 不支持 React 17 jsx transformer,inject 配置选项 transform api 也没有提供,当业务项目使用 React 版本为 17 时,并且没有显示导入 React 时, 我们在 esbuild transform 的结果上自动注入import React from 'react'
  2. 业务 TS 项目中有很多使用了 const enum 导致 esbuild 无法处理,只能切换到 typescript api 处理。
  3. 老项目业务代码中依赖 babel 生态的插件, 比如babel-plugin-macros[5], 这就导致我们额外需要提供 babel 编译的流程。

基础的语法转换完成后,接下来就是 Bare Import 的处理问题,我们的业务代码中直接通过包名导入依赖的方式经过打包工具处理能够正常运行, 如下:

import React from 'react'  

但是在浏览器中直接运行会直接报错,import-maps[6]提案可以解决这个问题,但是只有最新版本 Chrome 支持。这里我们采用的方案和业界的做法一致,编译完成后改写 import 语句, 以 React 为例, 最终返回的内容如下:

import React from "/node_modules/.web_modules/react.js";  

node_modules/.web_modules目录就是我们在依赖预处理时生成的第三方依赖 ESM 文件目录。

CSS、JSON、图片等资源处理

浏览器中直接 import 导入资源,要求返回的类型是application/javascript,因此这些文件在对应的插件中最终都会被处理成 JavaScript。

CSS 默认会用 PostCSS 处理之后直接创建 style 标签插入 head 节点就能生效,以import ./App.css为例,返回的内容大致如下:

// src/App.css  
const code = "body {\n  margin: 0;\n}\n"  
const filename = "/Users/songzhenwei/Documents/test/full-demo/src/App.css"  
const styleEl = document.createElement('style');  
const codeEl = document.createTextNode(code);  
styleEl.type = 'text/css';  
styleEl.appendChild(codeEl);  
document.head.appendChild(styleEl);  

这里只是简单展示返回文件的内容,真正可用还需要考虑热更新时 Style 标签的删除、CSS 文件中通过 [url function](https://developer.mozilla.org/en-US/docs/Web/CSS/url()) 加载字体图片等场景。

JSON 文件比较简单,这里我们只需要读取文件 default 导出即可:

export default { "name": "example" }  

业务代码中使用图片等资源时, 我们会在 import 语句后面添加?assetsquery 表示为资源请求需要编译处理, 如下:

import logo from './logo.png';  
// => rewrite to   
import logo from '/src/logo.png?assets'  

/src/logo.png?assets直接返回对应资源的实际 url 即可:

export default '/src/logo.png'  

对于图片资源,实际业务场景中我们还需要支持根据文件尺寸决定是否通过 base64 编码内联、svgr 等特性。

到这里通过不同的插件完成了一些文件类型的编译转换,页面已经可以在浏览器中正确渲染。

热更新功能

在 Webpack 等打包工具里面,热更新相关代码通常写在入口文件内如下:

// src/index.jsx  
import App from './App';  

module.hot.accept('./App', () => {  
   renderApp();  
})  

App 根组件中引用到的文件修改时,会触发入口文件中注册的 accept 回调函数重新渲染 App 组件。

ESM 场景下的 HMR API, 业界也有一些规范:Snowpack 联合 Vue、Preact 提出了ESM-HMR Spec[7],类似module.hot, unbundled 开发工具需要提供import.meta.hot对象,比如常用的accept函数使用如下:

import.meta.hot.accept();  

import.meta.hot.accept(['./dep1', './dep2'], ()=> {})  

这部分实现参考了 Snowpack 和 Vite , 文件更新时,通过内部建立好的依赖关系,上溯至 accept 该文件或自身的文件节点,重新在浏览器请求该文件, 如下图:

修改dep-b.js向上遍历依赖树时,找到 accept 的文件节点App.tsx, 同时会依赖路径上文件节点的编译缓存失效,之后通过 HMR client api 重新请求App.tsx,为了保证返回的内容是最新的,重新请求时会加上时间戳。

和 Webpack 等打包工具热更新相比,Unbundled Development 开发工具热更新只会重新编译加载依赖路径上的文件, 因此速度也会更快。同时也能结合 React Fast Refresh 做组件级别的热更新。

总结

上面通过一些小点,介绍了我们内部解决 Webpack 打包慢的一些探索以及最终实现 Unbundled Development 模式的一些做法, 最终实现的版本和我们应用开发的标准范式一一对齐。在业务项目中使用 Unbundled Development 模式后开发体验有很大提升:

生产环境现阶段还是通过 Webpack 打包出 JS Bundle ,在一些基础编译能力以及使用方式上尽最大努力抹平 Unbundled Development 模式和生产环境 Webpack 打包的差异。

通过实际业务项目接入 Unbundled Development 模式实践,我们这边也针对 CJS 转 ESM 积累了一定的解决方案。通过云端统一处理的方式,后续也能发挥出更大的作用。一些新的方案如免依赖安装也在持续探索中,最后,我们也希望能对 Unbundled Development 生态添砖加瓦,最后反哺生态。

参考资料

[1]Webpack:https://webpack.js.org/guides/build-performance/

[2]Build Performance Guide:https://webpack.js.org/guides/build-performance/

[3]lazy-compile-webpack-plugin:https://github.com/liximomo/lazy-compile-webpack-plugin

[4]rollup-plugin-cdn:https://github.com/WebReflection/rollup-plugin-cdn

[5]@pika/cdn-webpack-plugin:https://www.npmjs.com/package/@pika/cdn-webpack-plugin

[6]@pika/cdn-webpack-plugin:https://www.npmjs.com/package/@pika/cdn-webpack-plugin

[7]babel-plugin-macros:https://github.com/kentcdodds/babel-plugin-macros

[8]import-maps:https://github.com/WICG/import-maps#the-basic-idea

[9]ESM-HMR Spec:https://github.com/snowpackjs/esm-hmr

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

 相关推荐

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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