博客

  • WordPress 插件

    WordPress 插件

    WordPress 是一款功能多样的出色 CMS(内容管理系统)。借助合适的插件,您可以将 WordPress 从简单的博客平台转变为功能强大且灵活的自定义网站。WordPress 提供超过 45,000 个免费插件,用户可以轻松选择。 

    在本文中,我们将介绍什么是插件以及为什么要使用它们,并举例说明一些最受欢迎的插件。您还将学习如何找到适合您需求的 WordPress 插件并将其安装在您的网站上。 

    什么是 WordPress 插件?

    WordPress 插件是一小段软件,可以为您的网站添加功能。WordPress 用户可以通过 WordPress 管理面板将这些插件安装在他们的网站上。数以千计的免费和付费插件可以帮助您完成所有事情,从添加联系表单到运营在线商店。 

    使用 WordPress 插件有两个主要优势:无需编码知识,并且它们可以为您的网站添加您可能无法从头开始构建的功能。插件可帮助您简化网站的功能并使其更易于管理。例如,您可以使用 CRM(客户关系管理)插件快速轻松地将网站访问者转移到您的销售渠道。如果您手动执行此操作,则会花费大量时间,并且扩展起来会困难得多。 

    插件带来了 WordPress 核心所不具备的功能,这些功能非常有用。例如,有些插件可让您在不了解任何代码的情况下向网站添加交互式地图。还有一些 SEO 优化插件可帮助您在搜索引擎中排名更高。这些只是一些基本插件。

    为什么要使用 WordPress 插件?

    插件可让您免去一些最费力的手动任务,从而让生活变得更轻松。它们还可以通过添加新功能来帮助提高网站的性能和覆盖范围。事实上,如果使用得当,插件可以将您的网站转变为远远超出基本网站的东西。 

    以下是您应该使用 WordPress 插件的一些原因: 

    • 节省时间——插件可以使某些耗时的任务变得更快,例如在您的网站添加事件日历或缩短 URL。 
    • 添加自定义功能– 每个网站和企业都有不同的需求,您无法从头开始将每个功能都构建到您的网站中。插件可以帮助您从头开始构建电子商务商店并轻松吸引新闻通讯订阅者。
    • 提高您网站的性能——插件可以帮助提高您网站的页面加载速度并测试您的视觉内容是否存在错误。 
    • 获得新的受众——插件可以帮助您扩大社交和自然搜索受众,接触到以前可能无法接触到的人。 
    • 保护您的内容——插件可以帮助您的 WordPress 网站更加安全并防止垃圾邮件。

    WordPress 插件的类型

    WordPress 插件有很多种类型,但一般可以分为五类:功能、安全、流量生成、电子商务和内容。

    • 功能– 这些插件最为常见,几乎可以实现您能想到的所有功能。这些插件可以提升您网站的用户体验,让访问者以有意义的方式与您的内容互动。 
    • 安全性– 这些对于保护您的内容免受黑客攻击至关重要。您需要在网站上安装安全插件,以防止未经授权的访问并保护客户数据。 
    • 流量生成——这些插件可帮助您提升 Google 排名、电子邮件列表和社交媒体影响力等,从而吸引更多访问者访问您的网站。 
    • 电子商务– 如果您想在网站上销售产品,您需要一个电子商务插件。这些插件可能非常强大,但在为您的商店选择最佳插件时需要仔细考虑。 
    • 内容– 这些插件管理您网站上的内容,例如您的博客文章、页面和图片。虽然它们可能会影响网站访问者看到的内容,但内容插件更多地是关于您如何在后端管理资源。

    如何为你的网站找到合适的插件

    要为您的 WordPress 网站选择最佳插件,您首先需要考虑您需要什么功能以及您的用户可能想要什么。花一些时间集思广益,并写下属于每个类别的长列表。请您的团队或朋友提供想法。任何同时出现在两列中的功能都应优先考虑。 

    确定了首要任务后,您就可以搜索合适的插件了。以下是查找插件的一些技巧: 

    • 比较免费版和付费版——许多插件都提供免费版和付费版。在许多情况下,免费插件可以满足您的大部分需求。但在探索插件功能时,请注意必须付费的额外功能。并注意付费版费用是一次性的还是定期的。 
    • 阅读评论– 找到一些看起来不错的插件后,请阅读评论,看看其他人对它们的看法。这将帮助您更好地了解插件的效果和易用性。请记住,插件不适合其他用户并不意味着它不适合您。考虑好评和差评,以做出明智的决定。
    • 阅读说明– 大多数插件都会有安装指南,向您展示如何设置插件。安装前,请花点时间阅读开发人员的任何说明或警告,以避免潜在的兼容性问题。
    • 找到合适的支持– 安装插件后,您可能不时需要帮助。找到一个支持论坛,您可以在那里询问有关插件的问题。

    安装 WordPress 插件

    找到满足您需求的最佳插件后,就可以安装它们了!值得庆幸的是,这个过程非常简单,大多数插件都会引导您完成安装过程。 

    根据您使用的托管类型,此过程略有不同。例如,EasyWP 的托管 WordPress 托管可为您节省几个步骤(和一点时间)。以下是适用于托管托管的安装步骤:

    1. 从 WordPress 仪表板导航到插件菜单并单击添加新插件。
    2. 在搜索栏中按名称或功能搜索插件
    3. 单击“立即安装”
    4. 点击激活

    现在您知道了什么是 WordPress 插件以及它们的作用,让我们来看看一些最受欢迎的插件。 

    WooCommerce

    WooCommerce 是一个开源电子商务平台,可让您在网站上在线创建和销售产品。它免费使用,并且 WooCommerce 有数千个附加插件可供您自定义商店的外观和功能。

    WooCommerce 让任何人(从初学者到经验丰富的 Web 开发人员和设计师)都能够使用 WordPress 的 WooCommerce 插件轻松创建商店。了解有关 WooCommerce和其他四个电子商务插件的更多信息。 

    优斯特搜索引擎优化

    Yoast SEO 是一款 WordPress 插件,可分析您网站的内容并提供可遵循的指南来提高您在 Google 上的排名。简单来说,Yoast SEO 会检查您网站的四个主要元素(标题、元描述、架构和站点地图),以确保它们都符合 Google 的指南。

    它还会检查错误、断开的链接、重复的内容和其他问题。

    WPForms表单插件

    WPForms 是一款 WordPress 表单询盘插件,可让您在几分钟内为您的网站创建联系表单。它具有可自定义的设计、易于使用的界面以及与 MailChimp 和 Mandrill 等电子邮件服务的内置集成。您还可以从其他来源(例如 Google 和 Facebook)导入联系人。

    WPForms 界面简洁直观,非常适合初学者或任何想在网站上轻松创建表单的人。它还具有高度可定制性,可让每个表单完全按照您的要求设计。它还支持移动设备,因此每个人都可以使用它。

    Max Mega Menu 多功能菜单插件

    Max Mega Menu 是一款 WordPress 多功能菜单插件,可让您在网站上创建大型菜单。它对于餐厅、咖啡馆和其他向客户提供多种菜肴的企业非常有用。通过使用 Max Mega Menu,您可以一次显示整个菜单,从而节省空间并让客户更容易找到他们想要的东西。

    Max Mega Menu 的主要优势在于它能让您的企业脱颖而出。一次性显示整个菜单可吸引顾客的注意力,让顾客更容易找到他们想要的菜品。

    关于 WordPress 插件安全性的说明

     WordPress 插件是一种轻松扩展 WordPress 网站功能和性能的方法。但是,请注意:过时的插件可能会给您的网站带来安全风险。这些风险包括网络钓鱼攻击(攻击者试图诱骗用户提供敏感信息)和 SQL 注入攻击(网络犯罪分子会与数据库查询交互以获取他们通常无法看到的数据)。防止这些漏洞风险的最佳方法是确保您只安装来自可信来源的插件,并在安装插件时定期检查更新。

    探索插件的可能性

    WordPress 插件是向网站添加功能并使其更易于管理的绝佳方式。它们还可以帮助您提高网站的性能、吸引新受众并保护您的内容免受垃圾邮件的侵害。花时间为您和您的网站用户选择合适的插件非常重要,因为可能性是无穷无尽的。只需进行一些研究和努力,您就可以使用这些令人惊叹的多功能软件来拥有您梦想中的定制网站。

  • 尤雨溪成立VoidZero,Rust要一统JavaScript工具链?

    尤雨溪成立VoidZero,Rust要一统JavaScript工具链?

    尤雨溪在Vite Conf 2024上宣布成立公司Void Zero,目前已经完成$460万种子轮融资,由Accel领头,并且有Amplify以及在dev tools领域有丰富经验的创始人参与。 主要目标是搭建下一代JavaScript工具链,实现一套工具覆盖从源码到最终产物的中间过程,例如semantic analysis、transformer、linter、formatter、minifier、boundler等。

    image.png

    好的工具链不外乎好用, 本文将结合尤雨溪在Vite Conf 2024上分享的内容来介绍什么是下一代JavaScript工具链, 以及好用体现在哪些方面, 最后再上手试验下相关工具看是否真的

    Vite工具现状

    相信现在大多数前端开发人员的构建工具首选一定是Vite,Vite确实易上手并且快,涵盖了Vue、React、Preact等主流前端框架,也支持TypeScript、Nuxt等。Vite仅需简单的几个指令即可运行起项目:

    // 运行create指令,选择前端框架和语言,例如Vue、TypeScript
    npm create vite@latest
    
    // Done. Now run:
      
    cd vite-project
    npm install
    npm run dev

    Vite为什么快?

    有对比才能体现快,几年前构建前端项目还是使用webpack、Rollup、Parcel等工具,当项目代码指数级增长,这些工具的性能瓶颈愈发明显,动不动需要几分钟才能启动dev server,即使是模块热更新(HMR),文件修改后也需要几秒钟才能反馈到浏览器,这严重影响开发者工作幸福指数

    浏览器的快速发展造就了Vite,Vite的优势在两个方面:首先是支持了Native ES Modules,其次是build过程接入了编译型语言(如go、rust)开发的工具。这些优势体现在服务器启动和热更新两个阶段:

    • 服务器启动: Vite将应用中的模块区分为依赖、源码两种,改进了开发服务器启动时间。
      • 依赖:开发时不会变动的纯JavaScript,或者是较大的依赖(上百个模块的组件库),这些代码的处理代价比较高,Vite会使用esbuild预构建这些依赖,由于esbuild使用Go编写,因此比以JavaScript编写的打包器预构建快10-100倍。
      • 源码:对于Vue、JSX等频繁变动的代码文件,Vite以原生ESM方式提供源码,让浏览器接管了打包程序的部分工作,Vite只需要在浏览器请求源码时进行转换并安需提供,也就是需安需导入、安需加载。
      image.png
    • 热更新(HMR) 在Vite中,HMR是在原生ESM上执行的。当编辑一个文件时,Vite只需要精确地使已编辑Module与其最近的HMR边界之间的链失活,使得无论应用大小如何,HMR能保持快速更新。 Vite同时利用HTTP头来加速整个页面的重新加载:源码模块请求根据304 Not Modified协商缓存,而预构建的依赖模块请求则通过Cache-Control:max-age=31536000,immutable进行强缓存,因此一旦被缓存将不需要再次请求。

    Vite也有缺陷

    image.png

    Vite当前架构底层依赖于esbuildRollupSWC,三者的作用如下:

    • esbuild: Vite使用esbuild执行依赖项预构建,转化TypeScript、JSX,并且作为生成环境构建的默认minifier。
    • Rollup: Rollup直接基于ES6模块格式,因此能够实现除屑优化(Tree Shaking),然后基于插件生态来支持打包过程的扩展。Vite基于Rollup的插件模板实现插件生态,构建生产环境的bundling chunk和静态资源。
    • SWC: SWC使用Rust语言实现,号称super-fastJavaScript编译器,能够将TypeScript、JSX编译为浏览器支持的JavaScript,编译速度比babel快20倍。Vite主要使用SWC来打包React代码以及实现React代码的HMR。

    Vite充分利用esbuild、Rollup、SWC各自的优势来组合成一套打包工具链,虽然对使用者来说是无感的,但对于Vite内部,三套打包框架组合在一起本身就显得比较臃肿。

    接下来我们就分析下这一套组合拳会有哪些缺陷:

    • 两套bundling 虽然esbuild构建非常快,但它的tree shaking以及代码切分不像rollup的配置化那样灵活,插件系统设计的也不尽如人意,因此Vite仅在DEV环境使用esbuild预构建依赖项。rollup正好拟补了ebuild的缺点,比较好的chunck control,以及易配置的tree shaking,因此适合在生成环境打包代码。
    • 生产环境构建速度慢 由于Rollup基于JavaScript实现,虽然比Webpack快很多,但相比于native工具链,速度就相形见绌了。
    • 比较大的二进制包 SWC的二进制包有多大?在Mac系统下,达到37MB,比Vite和其依赖项文件总和大了2倍。
    • SWC虽然快,但缺少bundler能力 SWC有比较完善的transform和minifier,但没有提供可用的bundler,这也就说明了SWC不能直接作为打包工具。
    • 不一致的bundler行为 DEV环境使用esbuild预构建依赖项,而PROD环境使用rollup构建包,在包含ESM、CJS多模块形式场景下,esbuild和rullup的构建行为存在差异,导致一些仅在线上出现的问题。
    • 低效率的构建管道 由于混合了JavaScript、Go、Rust三种程序,同一代码片段可能会在不同进程重复执行AST、transform、serialize,并将结果在不同进程间传递。另一方面,在进程间传递大量的代码块本身也会有比较大的开销,特别是传递source map此类文件时开销更大。

    总结这些问题,就三点:碎片化、不兼容、低效率。 为了解决这些种种问题,统一的打包工具迫在眉睫,这也是尤雨溪提出Rolldown的主要原因。

    image.png

    基于Rust的下一代工具链

    image.png

    VoidZero提出的下一代工具链是什么?下图为 VoieZero规划蓝图,不管是Vue、React、Nuxt还是其他前端框架,一个Vite统统给你搞定,测试框架仅需Vitest即可。Vite底层依赖Rolldown打包器,而打包过程完全交由工具链Oxc负责。实际干活的RolldownOxc都基于Rust实现,因此够快。

    image.png

    OxcRolldown离正式使用还有一段距离,预计是2025年初投入使用,但这也不妨碍我们先了解下这两个工具让人惊掉下巴的牛,毕竟值460万美金。

    Oxc

    Oxc作为统一的语言工具链,将提供包含代码检查Linter、代码格式化Formatter、代码打包的组合式NPM包或者Rust包。代码打包过程分为TransformerMinifierResolverParserSemantic Analysis

    Oxc官网地址: oxc.rs/ , 目前已经发布了oxlint v0.9.9oxc-transform alpha 版本

    • oxlint v0.9.9检查速度比eslint快50-100倍。oxlint已经在Shopify投入使用,之前使用eslint检查代码需要75分钟/CI,而使用oxlint仅需要10秒钟,你就说快吧!
    • oxc-transform alpha转换速度是SWC的3到5倍, 并且内存占用减少20%, 更小的包体积(2MB vs SWC的37MB). 已实现的主要3个功能:
      • 转换TypeScript至ESNext;
      • 转换React JSX至ESNext,并支持React Refresh;
      • TypeScript DTS 声明;

    Oxc目前已完成Parser Linter Resolver,正在快马加鞭地完善Transformer

    image.png

    Rolldown

    Rolldown是基于Rust实现的JavaScript快速打包器,与Rollup API兼容。作为打包器应包含的功能有:

    • Bundling:
      • 阶段1:使用Rolldown替换esbuild,执行依赖项预生成,主要包括多entry的代码切分、cjs/esm混合打包、基础插件支持;
      • 阶段2:Rolldown能够支持生成环境构建,包括命令行和配置文件支持、Treeshaking、Source map、Rollup插件兼容等;
    • Transform: 使用oxc代替esbuild的Transform,尽可能使用同一套AST。核心功能模块Typescript/JSX转换、代码缩减(minification)以及语法降级;
    • 与Vite深度集成: 替换esbuild和rollup,Vite内部核心插件使用Rust实现,提升构建效率。
    image.png

    Rolldown在性能方面表现如何?官方给出了两个测试。

    测试一:打包数量为19k的模块文件,其中10k为React JSX组件,9k为图标js文件。不同打包框架的耗时如下:

    • rolldown: 0.63s
    • rolldown-vite: 1.49s
    • esbuild: 1.23s
    • fram: 2.08s
    • rsbuild: 3.14s

    rolldown打包速度比esbuild快了近2倍。

    测试二:打包Vue Core代码,基于TypeScript的多包仓库,包含11个包/62个dist bundles,耗时如下:

    Vue版本构建框架构建耗时
    Vue3.2Rollup + rullup-plugin-typescript2+ terser tsx114s
    Vue3.5(main branch)Rollup + rollup-plugin-esbuild + swc minify tsc8.5s
    Vue3.5(rolldown branch)Rolldown(tranform+minify) + oxc-transform1.11s

    基于rolldown的Vue3.5源代码比Rollup构建快了近8倍。

    单从测试数据来看,基于Rust开发的rolldown,打包速度确实带来惊人的提升。以下为下一代Vite的架构概览,预计2025年初发布。

    image.png

    总结

    VoidZero宣称的下一代JavaScript工具链,价值460万美金,其商业价值可见一斑,对于研发个体来说没有明显的感受,但对于大型企业来说,VoidZero能实打实的为企业节省每年几百万的CI构建成本。

    VoidZero将清一色的使用Rust来搭建底层构建逻辑,如果能够成型,也证明了Rust在前端构建领域的地位。这也让我们反思,借助于Rust独特的性能和安全性优势,它还能够为前端带来哪些价值?例如WASM支持,基于Tauri、Electon.rs框架的桌面应用,支持Flutter和Dart语言的移动端应用。

    究竟VoidZero会为前端领域带来怎样的变革,Vite能不能一统JavaScript工具链,让我们拭目以待吧。

    作者:前端下饭菜
    链接:https://juejin.cn/post/7422404598360948748
    来源:稀土掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • Vite 6.0 发布了!(2024年11月26日)

    Vite 6.0 发布了!(2024年11月26日)

    Vite 6 Announcement Cover Image

    今天,Vite 迎来了发展历程中的重要里程碑。我们很高兴地宣布,Vite 6 正式发布了!这一重大版本的发布离不开 Vite 团队贡献者 以及整个生态系统合作伙伴的共同努力。

    过去一年中,Vite 的采用率持续增长,自 Vite 5 发布以来,npm 每周下载量从 750 万次跃升至 1700 万次。Vitest 不仅越来越受用户欢迎,还开始形成自己的生态系统。例如,Storybook 推出了由 Vitest 支持的全新测试功能。

    Vite 生态系统也迎来了一批新成员,包括 TanStack StartOneEmber 等框架。Web 开发领域的创新速度日益加快,AstroNuxtSvelteKitSolid StartQwik CityRedwoodJSReact Router 等项目都在不断推陈出新。

    Vite 已被 OpenAI、Google、Apple、Microsoft、NASA、Shopify、Cloudflare、GitLab、Reddit 和 Linear 等众多知名公司采用。两个月前,我们创建了一份 使用 Vite 的公司列表。令人欣喜的是,许多开发者提交 PR 将他们的公司添加到列表中。回首 Vite 诞生至今,我们共同打造的生态系统增长速度之快,实在令人难以置信。

    Vite weekly npm downloads

    加速 Vite 生态系统

    上个月,StackBlitz 再次主办了第三届 ViteConf,吸引了整个社区的广泛参与。这是迄今为止规模最大的 Vite 会议,生态系统中的各路开发者齐聚一堂。Evan You 正式宣布成立 VoidZero,这是一家致力于为 JavaScript 生态系统构建开源、高性能和统一开发工具链的公司。VoidZero 推出了 Rolldown 和 Oxc,他们的团队正在加紧准备这些工具以供 Vite 采用。想了解 Vite 未来如何借助 Rust 实现更强大的性能,不妨观看 Evan 的主题演讲。

    https://youtube.com/watch?v=EKvvptbTx6k%3Fsi%3DEZ-rFJn4pDW3tUvp

    Stackblitz 推出了 bolt.new,这是一个结合了 Claude 和 WebContainers 的 Remix 应用,允许你使用提示语、编辑、运行和部署全栈应用。Nate Weiner 宣布了 One,一个新的 Vite 驱动的 Web 和原生 React 框架。Storybook 展示了他们最新由 Vitest 驱动的 测试功能。还有更多精彩内容。我们建议你观看 全部 43 场演讲。演讲者们付出了巨大努力,分享了每个项目的最新进展。

    Vite 还更新了主页和域名。请记得将你的链接更新为新的 vite.dev 域名。新设计和实现由 VoidZero 完成,正是他们制作了自己的网站。特别感谢 Vicente Rodriguez 和 Simon Le Marchant 的贡献。

    Vite 6 的到来

    Vite 6 是自 Vite 2 以来最重要的主要版本发布。我们渴望与生态系统合作,通过新的 API 继续扩展我们的共享资源,并一如既往地提供一个更完善的构建基础。

    快速链接:

    如果你是 Vite 的新用户,我们建议首先阅读 入门指南 和 功能介绍 部分。

    我们要感谢超过 1000 位 Vite Core 贡献者 以及 Vite 插件、集成、工具和翻译的维护者和贡献者,他们帮助我们打造了这个新的主要版本。我们也邀请你参与进来,帮助我们改进整个生态系统的 Vite。了解更多信息,请参阅我们的 贡献指南

    如果准备开始的话,我们建议可以帮助 分类问题审查 PR、根据开放问题发送失败的测试 PR,并在讨论 和 Vite Land 的 帮助论坛 中帮助他人。如果你想与我们交流,请加入我们的 Discord 社区 并在 #贡献频道 中打个招呼。

    有关 Vite 生态系统和 Vite Core 的最新消息,请关注我们的 BlueskyX 或 Mastodon

    开始使用 Vite 6

    你可以使用 pnpm create vite 快速搭建一个 Vite 应用,使用你喜欢的框架,或在线体验 Vite 6,访问 vite.new。你还可以运行 pnpm create vite-extra 以获取其他框架和运行时(Solid、Deno、SSR 和库起始模板)的模板。当你在 create vite 下选择 Others 选项时,也可以使用 create vite-extra 模板。

    Vite 启动模板旨在作为测试 Vite 与不同框架结合的演练场。在构建下一个项目时,你可以试着使用每个框架推荐的启动模板。create vite 还提供了一些框架的快捷设置,如 create-vueNuxt 3SvelteKitRemixAnalog 和 Angular

    Node.js 支持

    Vite 6 与 Vite 5 类似,支持 Node.js 18、20 和 22+。Node.js 21 的支持已被移除。Vite 在旧版本的 Node.js 生命周期终止 (EOL)后停止支持。Node.js 18 EOL 在 2025 年 4 月底,届时我们可能会发布一个新主要版本以提高所需的 Node.js 版本。

    实验性环境 API

    Vite 正在通过新的环境 API 变得更加灵活。这些新 API 将允许框架作者提供更接近生产环境的开发体验,并为生态系统共享新的构建模块。如果你正在构建一个 SPA,使用 Vite 的单一客户端环境,一切将如以往一样工作。即使对于自定义 SSR 应用,Vite 6 也向后兼容。环境 API 的主要目标受众是框架作者。

    对于感兴趣的终端用户,Sapphi 撰写了一篇很好的 环境 API 介绍 指南。这是一个很好的起点,帮助你理解我们为何努力使 Vite 更加灵活。

    如果你是框架作者或 Vite 插件维护者,并希望利用新 API,你可以在 环境 API 指南 中了解更多信息。

    我们要感谢所有参与定义和实现新 API 的伙伴。这个故事始于 Vite 2 采用了由 Rich Harris 和 SvelteKit 团队开创的无打包 SSR 开发方案。Vite 的 SSR 转换随后启发了 Anthony Fu 和 Pooya Parsa 创建 vite-node 并改进 Nuxt 的开发 SSR 方案。Anthony 之后使用 vite-node 为 Vitest 提供支持,而 Vladimir Sheremet 在维护 Vitest 的过程中也在不断改进它。2023 年初,Vladimir 开始将 vite-node 上游合并到 Vite Core 中,一年后我们在 Vite 5.1 中将其作为 Runtime API 发布。来自生态系统合作伙伴(特别感谢 Cloudflare 团队)的反馈推动我们对 Vite 的环境进行更雄心勃勃的重构。你可以在 Patak 的 ViteConf 24 演讲 中了解更多关于这个故事的信息。

    Vite 团队的每个人都参与了新 API 的定义,该 API 是与生态系统中许多项目的反馈共同设计的。感谢所有参与者!如果你正在基于 Vite 构建框架、插件或工具,我们鼓励你参与进来。新 API 是实验性的。我们将与生态系统合作,审查新 API 的使用方式,并在下一个主要版本中稳定它们。如果你想提问或反馈意见,这里有一个 开放的 GitHub 讨论

    主要变化

    此外,还有一个新的 破坏性变更 页面,列出了 Vite 中所有计划的、正在考虑的和过去的更改。

    迁移到 Vite 6

    对于大多数项目,升级到 Vite 6 应该是很直接的,但我们建议在升级前查看 详细的迁移指南

    完整的更改列表请参见 Vite 6 更新日志

  • Akamai成为Linux内核基础架构合作伙伴

    Akamai成为Linux内核基础架构合作伙伴

    2025年4月22日,全球云服务提供商Akamai宣布其现已成为 Linux 内核开发工作的新基础架构合作伙伴。Akamai 将通过其云计算服务和内容交付网络 (CDN) 为 kernel.org 提供支持。

    赋能开发者共同体的可持续发展

    Akamai 与 Linux Kernel Organization 签订了一项多年合作协议,未来将为 Linux 项目及其背后的开发者网络提供基础设施支持。Linux 的开发者中有许多都是志愿者,他们的持续贡献对于保障系统安全性、性能和可用性至关重要。如今,全球政府、科研机构、非营利组织以及企业广泛使用 Linux 系统,涵盖从智能手机、工业设备到云数据中心和金融交易平台等多个关键领域。

    Linux 内核庞大而复杂,目前代码量已超过 2800 万行。自 2005 年以来,来自超过 1300 家企业的 13,500 多名开发者为其做出贡献。开发者们不断迭代内核代码,并将其分发给构建各种 Linux 发行版的技术团队。Akamai 提供的基础架构服务将确保他们能够安全、高效地访问这些源代码。

    开源共生:从技术反哺到生态繁荣

    Akamai Cloud 首席架构师兼 CNCF 技术监督委员会成员 Alex Chircop 表示:“Akamai 的平台本身就建立在 Linux 和开源技术之上。我们为 kernel.org 提供支持,是对社区的回馈,也延续了我们对 CNCF 的承诺。这正是 Linode 中 ‘Lin’ 的来源——对 Linux 的致敬。”

    Akamai 的开源承诺不仅止步于 Linux。CNCF 首席技术官 Chris Aniszczyk 表示:“Akamai 是开源社区的重要一员。无论是对 OpenTelemetry、Argo和Prometheus 等关键项目的贡献,还是向 CNCF 项目捐赠 100 万美元的基础设施额度,都体现了他们对开源人才和项目的坚定支持。”

    作为 CNCF 的金牌会员以及 KubeCon 的白金赞助商,Akamai在 2022 年收购了 Linux 云服务先锋 Linode,随后于 2023 年又将 Kubernetes 原生存储平台 Ondat 收入麾下,进一步扩展了其开源与云原生的实力。目前,Akamai 旗下的 Linode Kubernetes Engine 已获得 CNCF 的 Kubernetes 一致性认证,是一款全面托管的容器编排平台,致力于简化云原生应用的部署与管理。

    作为对其开源支持承诺的一部分,Akamai 还宣布将为备受欢迎的Linux 发行版之一 Alpine Linux 提供基础架构与交付支持。

    通过为Linux内核及Alpine Linux提供基础设施支持,Akamai正在帮助全球开发者更高效地协调合作。这种基于实际技术能力的回馈方式,不仅提升了开源协作效率,更展现了商业公司与开源社区协同发展的可持续模式。未来,Akamai依然会持续地回馈开源社区,助力开源生态繁荣发展。

  • 苹果新专利:事件相机系统

    苹果新专利:事件相机系统

    近日有技术资料显示,苹果公司获得了一项新的专利授权,涉及一种先进的事件相机系统方案,未来可能应用于包括 MacBook 在内的多种设备。

    目前常见的相机在捕捉动态场景时存在局限,特别是在处理高速动作方面表现不足。而事件相机技术则能以像素为单位记录画面变化,实现更快的数据响应速度。不过,在复杂场景中,大量非目标信息可能影响识别效率。

    针对这一问题,苹果提出了一种解决方案:通过融合传统帧相机的信息,锁定关键区域,例如用户的手部,从而更高效地处理有效数据。该方法利用帧相机图像划定感兴趣区域,比如用“边界框”来定位手部位置,过滤掉无关背景信息,只对目标区域内发生的事件进行分析处理。

    除此之外,事件相机还支持红外波段探测,有助于降低环境干扰。系统也可以通过分析连续的事件区块来判断手指或手掌的移动轨迹,相比单独解析每个事件,这种方法在准确性和效率方面更具优势。

    这项技术的应用范围并不仅限于笔记本电脑。根据资料显示,其未来还有望应用于智能手表、智能手机、平板电脑、穿戴式显示设备以及家庭智能装置等多种产品当中。

  • 常用开源协议介绍

    常用开源协议介绍

    开源协议别名LGPL许可证。LGPL许可证是LESSER GENERAL PUBLIC LICENSE的简写,也叫LIBRARY GENERAL PUBLIC LICENSE,中文译为“较宽松公共许可证”或者“函数库公共许可证”。该许可证适用于一些由自由软件基金会与其它决定使用此许可证的软件作者所特殊设计的软件包─比如函数库(即Library)。

    除了大家比较熟悉的GPL协议之外,开源界还有很多许可证,如LGPL许可证、BSD许可证等,下面就来一一介绍。

    LGPL许可证,也是自由软件联盟GNU开源软件许可证的一种,大部分的 GNU软件,包括一些函数库,是受到原来的 GPL许可证保护的。而LGPL许可证,适用于特殊设计的函数库,且与原来的通用公共许可证有很大的不同,给予了被许可人较为宽松的权利,所以叫“较宽松公共许可证”。在特定的函数库中使用它,以准许非自由的程序可以与这些函数库连结。

    当一个程序与一个函数库连结,不论是静态连结或使用共享函数库,二者的结合可以合理地说是结合的作品,一个原来的函数库的衍生品。因此,原来的通用公共许可证只有在整个结合品满足其自由的标准时,才允许连结。较宽松通用公共许可则以更宽松的标准允许其它程序代码与本函数库连结。例如,在少数情况下,可能会有特殊的需要而鼓励大家尽可能广泛地使用特定的函数库,因而使它成为实际上的标准。为了达到此目标,必须允许非自由的程序使用此函数库。一个较常发生的情况是,一个自由的函数库与一个被广泛使用的非自由函数库做相同的工作,在此情况下,限制只有自由软件可以使用此自由函数库不会有多少好处,故我们使用了LGPL许可证。

    在其他情况下,允许非自由程序使用特定的函数库,可以让更多的人们使用自由软件的大部分。例如,允许非自由程序使用GNU C函数库,可以让更多的人们使用整个GNU作业系统,以及它的变形,GNU/Linux操作系统。

    尽管LGPL许可证对使用者的自由保护是较少的,但它却能确保与此函数库连结的程序的使用者拥有自由,而且具有使用修改过的函数库版本来执行该程序的必要方法。

    MPL

    MPL是The Mozilla Public License的简写,是1998年初Netscape的 Mozilla小组为其开源软件项目设计的软件许可证。MPL许可证出现的最重要原因就是,Netscape公司认为GPL许可证没有很好地平衡开发者对源代码的需求和他们利用源代码获得的利益。同著名的GPL许可证和BSD许可证相比,MPL在许多权利与义务的约定方面与它们相同(因为都是符合OSIA认定的开源软件许可证)。但是,相比而言MPL还有以下几个显著的不同之处:

    ◆ MPL虽然要求对于经MPL许可证发布的源代码的修改也要以MPL许可证的方式再许可出来,以保证其他人可以在MPL的条款下共享源代码。但是,在MPL许可证中对“发布”的定义是“以源代码方式发布的文件”,这就意味着MPL允许一个企业在自己已有的源代码库上加一个接口,除了接口程序的源代码以MPL许可证的形式对外许可外,源代码库中的源代码就可以不用MPL许可证的方式强制对外许可。这些,就为借鉴别人的源代码用做自己商业软件开发的行为留了一个活口。

    ◆ MPL许可证第三条第7款中允许被许可人将经过MPL许可证获得的源代码同自己其他类型的代码混合得到自己的软件程序。

    ◆ 对软件专利的态度,MPL许可证不像GPL许可证那样明确表示反对软件专利,但是却明确要求源代码的提供者不能提供已经受专利保护的源代码(除非他本人是专利权人,并书面向公众免费许可这些源代码),也不能在将这些源代码以开放源代码许可证形式许可后再去申请与这些源代码有关的专利。

    ◆ 对源代码的定义

    而在MPL(1.1版本)许可证中,对源代码的定义是:“源代码指的是对作品进行修改最优先择取的形式,它包括:所有模块的所有源程序,加上有关的接口的定义,加上控制可执行作品的安装和编译的‘原本’(原文为‘Script’),或者不是与初始源代码显著不同的源代码就是被源代码贡献者选择的从公共领域可以得到的程序代码。”

    ◆ MPL许可证第3条有专门的一款是关于对源代码修改进行描述的规定,就是要求所有再发布者都得有一个专门的文件就对源代码程序修改的时间和修改的方式有描述。

    BSD

    BSD开源协议是一个给于使用者很大自由的协议。基本上使用者可以”为所欲为”,可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。

    但”为所欲为”的前提当你发布使用了BSD协议的代码,或者以BSD协议代码为基础做二次开发自己的产品时,需要满足三个条件:

    ◆如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协议。

    ◆如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议。

    ◆不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。

    BSD 代码鼓励代码共享,但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上开发商业软件发布和销售,因此是对 商业集成很友好的协议。而很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者二次开发

    GPL

    我们很熟悉的Linux就是采用了GPLGPL协议BSD, Apache Licence等鼓励代码重用的许可很不一样。GPL的出发点是代码的开源/免费使用和引用/修改/衍生代码的开源/免费使用,但不允许修改后和衍生的代 码做为闭源商业软件发布和销售。这也就是为什么我们能用免费的各种linux,包括商业公司的linux和linux上各种各样的由个人,组织,以及商 业软件公司开发的免费软件了。

    GPL协议的主要内容是只要在一个软件中使用(”使用”指类库引用,修改后的代码或者衍生代码)GPL 协议的产品,则该软件产品必须也采用GPL协议,既必须也是开源和免费。这就是所谓的”传染性”。GPL协议的产品作为一个单独的产品使用没有任何问题, 还可以享受免费的优势。

    由于GPL严格要求使用了GPL类库的软件产品必须使用GPL协议,对于使用GPL协议的开源代码,商业软件或者对代码有保密要求的部门就不适合集成/采用作为类库和二次开发的基础。

    其它细节如再发布的时候需要伴随GPL协议等和BSD/Apache等类似。

    MIT

    MIT是和BSD一样宽范的许可协议,作者只想保留版权,而无任何其它的限制。也就是说,你必须在你的发行版里包含原许可协议的声明,无论你是以二进制发布的还是以源代码发布的。MIT协议又称麻省理工学院许可证,最初由麻省理工学院开发。被授权人权利:1、被授权人有权利使用、复制、修改、合并、出版发行、散布、再授权及贩售软件及软件的副本。2、被授权人可根据程式的需要修改授权条款为适当的内容。被授权人义务:在软件和软件的所有副本中都必须包含版权声明和许可声明。

    AL2.0

    Apache Licence是著名的非盈利开源组织Apache采用的协议。该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布(作为开源或商业软件)。需要满足的条件也和BSD类似:

    ◆需要给代码的用户一份Apache Licence

    ◆如果你修改了代码,需要在被修改的文件中说明。

    ◆在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明。

    ◆如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache Licence。你可以在Notice中增加自己的许可,但不可以表现为对Apache Licence构成更改。

    Apache Licence也是对商业应用友好的许可。使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售。

  • 怎么上传SVG到WordPress

    怎么上传SVG到WordPress

    众所周知,WP天生不支持SVG文件上传,尝试上传SVG你会看到如下错误

    我们怎么解决呢? 两种方法,一种下载插件如 SVG Support,另一种利用WP提供的钩子upload_mimes

    • 进到Panel或者其他文件编辑器 wp根目录-> 文件管理.
    • 编辑 wp-includes/functions.php文件
    function add_file_types_to_uploads($file_types){
      $new_filetypes = array();
      $new_filetypes['svg'] = 'image/svg+xml';
      $file_types = array_merge($file_types, $new_filetypes );
      return $file_types;
    }
    add_filter('upload_mimes', 'add_file_types_to_uploads');

    把上面的代码粘贴到文件最后一行,刷新后台就可以上传了。

  • Control-flow Integrity in V8

    Control-flow Integrity in V8

    Published 09 October 2023 · Tagged with security

    Control-flow integrity (CFI) is a security feature aiming to prevent exploits from hijacking control-flow. The idea is that even if an attacker manages to corrupt the memory of a process, additional integrity checks can prevent them from executing arbitrary code. In this blog post, we want to discuss our work to enable CFI in V8.

    Background

    The popularity of Chrome makes it a valuable target for 0-day attacks and most in-the-wild exploits we’ve seen target V8 to gain initial code execution. V8 exploits typically follow a similar pattern: an initial bug leads to memory corruption but often the initial corruption is limited and the attacker has to find a way to arbitrarily read/write in the whole address space. This allows them to hijack the control-flow and run shellcode that executes the next step of the exploit chain that will try to break out of the Chrome sandbox.

    To prevent the attacker from turning memory corruption into shellcode execution, we’re implementing control-flow integrity in V8. This is especially challenging in the presence of a JIT compiler. If you turn data into machine code at runtime, you now need to ensure that corrupted data can’t turn into malicious code. Fortunately, modern hardware features provide us with the building blocks to design a JIT compiler that is robust even while processing corrupted memory.

    Following, we’ll look at the problem divided into three separate parts:

    • Forward-Edge CFI verifies the integrity of indirect control-flow transfers such as function pointer or vtable calls.
    • Backward-Edge CFI needs to ensure that return addresses read from the stack are valid.
    • JIT Memory Integrity validates all data that is written to executable memory at runtime.

    Forward-Edge CFI

    There are two hardware features that we want to use to protect indirect calls and jumps: landing pads and pointer authentication.

    Landing Pads

    Landing pads are special instructions that can be used to mark valid branch targets. If enabled, indirect branches can only jump to a landing pad instruction, anything else will raise an exception.
    On ARM64 for example, landing pads are available with the Branch Target Identification (BTI) feature introduced in Armv8.5-A. BTI support is already enabled in V8.
    On x64, landing pads were introduced with the Indirect Branch Tracking (IBT) part of the Control Flow Enforcement Technology (CET) feature.

    However, adding landing pads on all potential targets for indirect branches only provides us with coarse-grained control-flow integrity and still gives attackers lots of freedom. We can further tighten the restrictions by adding function signature checks (the argument and return types at the call site must match the called function) as well as through dynamically removing unneeded landing pad instructions at runtime.
    These features are part of the recent FineIBT proposal and we hope that it can get OS adoption.

    Pointer Authentication

    Armv8.3-A introduced pointer authentication (PAC) which can be used to embed a signature in the upper unused bits of a pointer. Since the signature is verified before the pointer is used, attackers won’t be able to provide arbitrary forged pointers to indirect branches.

    Backward-Edge CFI

    To protect return addresses, we also want to make use of two separate hardware features: shadow stacks and PAC.

    Shadow Stacks

    With Intel CET’s shadow stacks and the guarded control stack (GCS) in Armv9.4-A, we can have a separate stack just for return addresses that has hardware protections against malicious writes. These features provide some pretty strong protections against return address overwrites, but we will need to deal with cases where we legitimately modify the return stack such as during optimization / deoptimization and exception handling.

    Pointer Authentication (PAC-RET)

    Similar to indirect branches, pointer authentication can be used to sign return addresses before they get pushed to the stack. This is already enabled in V8 on ARM64 CPUs.

    A side effect of using hardware support for Forward-edge and Backward-edge CFI is that it will allow us to keep the performance impact to a minimum.

    JIT Memory Integrity

    A unique challenge to CFI in JIT compilers is that we need to write machine code to executable memory at runtime. We need to protect the memory in a way that the JIT compiler is allowed to write to it but the attacker’s memory write primitive can’t. A naive approach would be to change the page permissions temporarily to add / remove write access. But this is inherently racy since we need to assume that the attacker can trigger an arbitrary write concurrently from a second thread.

    Per-thread Memory Permissions

    On modern CPUs, we can have different views of the memory permissions that only apply to the current thread and can be changed quickly in userland.
    On x64 CPUs, this can be achieved with memory protection keys (pkeys) and ARM announced the permission overlay extensions in Armv8.9-A.
    This allows us to fine-grained toggle the write access to executable memory, for example by tagging it with a separate pkey.

    The JIT pages are now not attacker writable anymore but the JIT compiler still needs to write generated code into it. In V8, the generated code lives in AssemblerBuffers on the heap which can be corrupted by the attacker instead. We could protect the AssemblerBuffers too in the same fashion, but this just shifts the problem. For example, we’d then also need to protect the memory where the pointer to the AssemblerBuffer lives.
    In fact, any code that enables write access to such protected memory constitutes CFI attack surface and needs to be coded very defensively. E.g. any write to a pointer that comes from unprotected memory is game over, since the attacker can use it to corrupt executable memory. Thus, our design goal is to have as few of these critical sections as possible and keep the code inside short and self-contained.

    Control-Flow Validation

    If we don’t want to protect all compiler data, we can assume it to be untrusted from the point of view of CFI instead. Before writing anything to executable memory, we need to validate that it doesn’t lead to arbitrary control-flow. That includes for example that the written code doesn’t perform any syscall instructions or that it doesn’t jump into arbitrary code. Of course, we also need to check that it doesn’t change the pkey permissions of the current thread. Note that we don’t try to prevent the code from corrupting arbitrary memory since if the code is corrupted we can assume the attacker already has this capability.
    To perform such validation safely, we will also need to keep required metadata in protected memory as well as protect local variables on the stack.
    We ran some preliminary tests to assess the impact of such validation on performance. Fortunately, the validation is not occurring in performance-critical code paths, and we did not observe any regressions in the jetstream or speedometer benchmarks.

    Evaluation

    Offensive security research is an essential part of any mitigation design and we’re continuously trying to find new ways to bypass our protections. Here are some examples of attacks that we think will be possible and ideas to address them.

    Corrupted Syscall Arguments

    As mentioned before, we assume that an attacker can trigger a memory write primitive concurrently to other running threads. If another thread performs a syscall, some of the arguments could then be attacker-controlled if they’re read from memory. Chrome runs with a restrictive syscall filter but there’s still a few syscalls that could be used to bypass the CFI protections.

    Sigaction for example is a syscall to register signal handlers. During our research we found that a sigaction call in Chrome is reachable in a CFI-compliant way. Since the arguments are passed in memory, an attacker could trigger this code path and point the signal handler function to arbitrary code. Luckily, we can address this easily: either block the path to the sigaction call or block it with a syscall filter after initialization.

    Other interesting examples are the memory management syscalls. For example, if a thread calls munmap on a corrupted pointer, the attacker could unmap read-only pages and a consecutive mmap call can reuse this address, effectively adding write permissions to the page.
    Some OSes already provide protections against this attack with memory sealing: Apple platforms provide the VM_FLAGS_PERMANENT flag and OpenBSD has an mimmutable syscall.

    Signal Frame Corruption

    When the kernel executes a signal handler, it will save the current CPU state on the userland stack. A second thread could corrupt the saved state which will then get restored by the kernel.
    Protecting against this in user space seems difficult if the signal frame data is untrusted. At that point one would have to always exit or overwrite the signal frame with a known save state to return to.
    A more promising approach would be to protect the signal stack using per-thread memory permissions. For example, a pkey-tagged sigaltstack would protect against malicious overwrites, but it would require the kernel to temporarily allow write permissions when saving the CPU state onto it.

    v8CTF

    These were just a few examples of potential attacks that we’re working on addressing and we also want to learn more from the security community. If this interests you, try your hand at the recently launched v8CTF! Exploit V8 and gain a bounty, exploits targeting n-day vulnerabilities are explicitly in scope!

  • 修改 WordPress 文章类型名称和分类法名称

    修改 WordPress 文章类型名称和分类法名称

    WordPress 自带文章类型的功能,比如页面、文章、媒体等都是一种文章类型,而有些主题和插件会添加额外的文章类型,我们通常将非系统自带的称之为自定义文章类型(Custom Post Type),比如 产品、项目等等。而这些自定义文章类型,通常也会注册有自己的分类法,我们通常称之为自定义分类法(Taxonomy)

    在我们做WordPress网站的时候,有时候可能需要修改文章类型以及自定义分类法的名称,对于懂代码的朋友来说,可能比较简单,但是对于普通用户来说,折腾代码真的太不保险了,所以,今天倡萌分享两个插件,可以满足普通用户的需求。

    使用 Custom Post Type Editor 修改文章类型名称

    使用 Custom Post Type Editor 插件,可以通过简单的仪表板用户界面自定义任何已注册自定义文章类型的文本名称、菜单名称或描述。无需编辑 PHP 文件!

    修改 WordPress 文章类型名称和分类法名称 - Cpt Editor 1
    Cpt Editor 1

    例如,您可以自定义以下自定义文章类型:

    • 自定义文章类型Posts(由 WordPress Core 创建)
    • 自定义文章类型Pages(由 WordPress Core 创建)
    • 自定义文章类型Media(由 WordPress Core 创建)
    • 由 WordPress 插件创建的任何自定义文章类型
    • 由 WordPress 主题创建的任何自定义文章类型

    这意味着您不再需要修改 PHP 文件来重命名自定义文章类型!

    下载 Custom Post Type Editor

    使用 Rename Taxonomies 修改分类法名称

    Rename Taxonomies 插件允许您使用简单的界面自定义任何分类法名称,无需编码。自定义的分类仅重命名,无需更改注册密钥,因此使用此插件不会引起任何分类冲突。

    • 轻松重命名任何分类法(例如,将“类别 Categories”重命名为“主题 Topics”
    • 重命名自定义分类法(由第三方插件添加)
    • 简单、直观的用户界面
    • 无需编码
    • 翻译准备
    • 兼容多语言插件
    修改 WordPress 文章类型名称和分类法名称 - Rename Taxonomies 1
    Rename Taxonomies 1

    下载 Rename Taxonomies

    文章来自wordpress大学

  • 台积电美国扩产:亏损加剧仍投建第三晶圆厂

    台积电美国扩产:亏损加剧仍投建第三晶圆厂

    台积电美国扩产:亏损加剧仍投建第三晶圆厂

    尽管位于美国的工厂在过去一年中出现了超过32亿元人民币的亏损,台积电仍持续推进在美国的扩张计划。公司高层表示,将在美国引入更先进的半导体制造产能。

    近日,台积电位于亚利桑那州的第三座晶圆厂正式动工。这一进展由台积电董事长兼总裁魏哲家在最新声明中披露,显示出公司在当地布局的决心。

    根据台积电发布的2024年度报告,虽然第一座亚利桑那工厂已实现量产,但由于从产品量产到营收确认存在时间差,导致设在美国的子公司TSMC Arizona Corporation在去年的亏损进一步扩大,亏损金额从2023年的约109.25亿元新台币上升至2024年的142.98亿元新台币。

    目前,亚利桑那工厂已获得包括苹果、英伟达、AMD、博通及高通在内的五家主要客户支持。业内普遍认为,随着这些客户逐步导入量产,配合后续第二、第三座晶圆厂的陆续投产,将有助于该地区产能逐步达到经济规模,从而缩小亏损幅度。

    按照规划,亚利桑那第一座晶圆厂已于去年第四季度开始使用4nm制程技术进行生产;第二座晶圆厂的厂房建设已告完成,目前正在进行厂务系统安装工作,包括无尘室和机电工程,预计这座工厂将采用3nm制程技术。

    至于刚刚开建的第三座晶圆厂,则被寄予更高期望,预计将采用2nm甚至更为先进的制程技术进行芯片制造。此举旨在通过在美国本土生产最高端半导体产品,以更好地应对客户需求的增长。

    文章来自中关村