news 2026/9/21 19:20:22

ice.js 构建配置完全指南:从 ice.config.mts 到源码级原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ice.js 构建配置完全指南:从 ice.config.mts 到源码级原理
  • 前端
  • Web框架
  • SSR
  • 前端构建
  • 插件系统
  • 微前端
  • 跨平台

【免费下载链接】ice

🚀 ice.js: The Progressive App Framework Based On React(基于 React 的渐进式应用框架)

项目地址:https://gitcode.com/gh_mirrors/ice1/ice
点击查看免费下载

ice.js(基于 React 的渐进式应用框架)将几乎所有构建行为收敛到单一配置文件ice.config.mts中。本文以官方「构建配置」文档为核心,完整讲解从路径别名、环境变量替换、产物分包、代码压缩、polyfill 策略到 SSR/SSG 服务端产物、路由定制等全量配置项,并结合仓库源码(packages/ice/src/config.ts、packages/webpack-config/src/index.ts)剖析每个配置项背后的实现机制与默认值来源,读完即可掌握 ice.js 工程的构建调优与疑难排查能力。

配置文件与基础写法

构建配置文件ice.config.mts

ice.js 支持常用的构建配置项,所有配置项均在ice.config.mts中设置。为了获得良好的类型提示,推荐使用ice.config.mts(ESM + TypeScript)作为配置文件:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ publicPath: '/', }));

defineConfig支持函数或对象两种入参,定义在 packages/ice/src/config.ts:当传入函数时先执行函数得到配置对象,再原样返回(空配置时返回{}),因此函数形式便于在配置内部读取process.env等环境信息做分支判断。仓库中的 examples/basic-project/ice.config.mts 即展示了函数式写法 + 环境变量分支(如process.env.ICE_ENV === 'common' ? 'warn' : 'error')。

所有配置项都会经过userConfig注册表(packages/ice/src/config.ts)进行validation校验和默认值注入,非法类型会在启动阶段被拦截。

兼容性配置.browserslistrc

构建的浏览器兼容性推荐配置在.browserslistrc文件中:

chrome 55

该文件会被getSupportedBrowsers读取,用于生成 PostCSS 的 autoprefixer、browserslist 目标,并参与 webpack 文件系统缓存的版本指纹计算(packages/webpack-config/src/index.ts 中以 browsers 列表的 MD5 作为缓存 key 的一部分)。更多规则可参考 browserslist 文档。

路径与产物配置

publicPath 与 devPublicPath

  • publicPath:类型string,默认值/,配置 Webpack 的output.publicPath,仅在执行build命令时生效;
  • devPublicPath:类型string,默认值/,与publicPath同理,仅在执行start命令时生效。

源码中两者的setConfig分别判断context.command === 'build'context.command === 'start'才将值合并进最终配置(packages/ice/src/config.ts),因此生产环境与开发服务器可以各自指定不同的资源前缀。publicPath最终会写入 webpack 的output.publicPath并同时用于 devServer 的devMiddleware.publicPath(packages/webpack-config/src/index.ts)。

outputDir

  • 类型:string
  • 默认值:build

构建产物输出目录,默认为项目根目录下的build目录。源码中当配置值不是绝对路径时会以rootDir为基准拼接(packages/webpack-config/src/index.ts)。

hash

  • 类型:boolean | string
  • 默认值:false

如果希望构建后的资源带 hash 版本,可将hash设为true,也可以设为contenthash按文件内容生成 hash 值:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ hash: 'contenthash', }));

源码中hash === true会被归一为hash:8,作为输出文件名模板js/[name]-[hash:8].js的组成部分(packages/webpack-config/src/index.ts)。注意:设置为contenthash这类字符串时,webpack 会按文件内容生成 hash,未变化的文件在多次构建间保持相同文件名,从而最大化浏览器缓存命中率。

htmlGenerating

  • 类型:boolean | object
  • 默认值:true

如果产物不想生成 html,可以设置为false;注意在 SSG 开启的情况下,强制关闭 html 生成将导致 SSG 失效。传入true与传入{}效果一致。

htmlGenerating.mode
  • 类型:'cleanUrl' | 'compat'
  • 默认值:'cleanUrl'

配置 HTML 生成文件的规则,避免某些服务器下非首页内容刷新后 404。两种模式的差别如下表:

Route//foo/foo/bar
cleanUrl/index.html/foo.html/foo/bar.html
compat/index.html/foo/index.html/foo/bar/index.html
  • cleanUrl:生成的文件路径与路由一致,通常用于支持自动省略.html后缀的现代服务器;
  • compat:生成兼容模式的路径文件,通常用于只能省略index.html的服务器。

该类型定义位于 packages/ice/src/types/userConfig.ts。

模块解析与外部依赖

alias

  • 类型:Record<string, string | false>
  • 默认值:{ "@": "./src/" }

ice.js 默认内置常用 alias 规则,项目大多数时候不需要配置即可更简单地导入模块:

-import CustomTips from '../../../components/CustomTips'; +import CustomTips from '@/components/CustomTips';

如需配置别名对 import 路径进行映射:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ alias: { pages: './src/pages', }, }));

源码实现中,以.开头的相对别名值会被自动拼接为相对项目根目录的绝对路径(packages/shared-config/src/getAlias.ts),因此上面pages: './src/pages'等价于根目录下的src/pages。同时 alias 支持false值,可用于显式禁用内置别名。

externals

  • 类型:Record<string, string>
  • 默认值:{}

设置哪些模块不打包,转而通过<script>或其他方式引入:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ externals: { react: 'React', 'react-dom': 'ReactDOM', }, }));

对应需要在document.ts或页面模板中添加 CDN 文件:

import { Main, Scripts } from 'ice'; function Document() { return ( <html lang="en"> <body> <Main /> + <script crossOrigin="" src="https://unpkg.com/react@18/umd/react.production.min.js"></script> + <script crossOrigin="" src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script> <Scripts /> </body> </html> ); } export default Document;

externals 配置会直接透传给 webpack 的output.externals(packages/webpack-config/src/index.ts),适合对 react 等体积大、更新频率低的三方库做 CDN 化处理。

crossOriginLoading

  • 类型:false | 'anonymous' | 'use-credentials'
  • 默认值:false

指定 webpack 启用 cross-origin 方式加载 chunk:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ crossOriginLoading: 'anonymous' }));

该值会被合并到 webpack 的output.crossOriginLoading(packages/ice/src/config.ts),在资源部署到 CDN 且需要跨域携带 Cookie 或凭证时很有用。

编译期变量替换:define

  • 类型:Record<string, string | boolean>
  • 默认值:内置{ 'process.env.NODE_ENV': 'development' | 'production'; 'import.meta.renderer': 'client' | 'server'; 'import.meta.target': string; }

define在编译时将代码中的全局变量替换成其他值或表达式,一般用于区分不同环境以执行不同代码逻辑:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ define: { ASSETS_VERSION: JSON.stringify('0.1.0'), AGE: '11', }, }));

在代码中直接使用对应变量:

console.log(ASSETS_VERSION); // 最终会被编译成: // console.log('0.1.0'); console.log(AGE); // 最终会被编译成: // console.log(11);

注意:编译时框架会对define的替换值进行类似字符串拼接的方式生成新代码,因此:

  • 对于引用数据类型(functionobject),必须使用JSON.stringify()处理;
  • 当要替换的全局变量是字符串时,也必须使用JSON.stringify()或手动多添加一对引号(如"'hello world'"),否则替换结果会是一个标识符而非字符串字面量,与预期不符。

在构建时这些变量通过 webpackDefinePlugin注入(packages/webpack-config/src/index.ts),同时框架默认注入import.meta.renderer(client/server)与import.meta.target等运行时变量(packages/ice/src/bundler/webpack/getWebpackConfig.ts)。对于运行时变量,ice.js 更推荐通过环境变量的方式注入。

代码优化与产物控制

minify

  • 类型:boolean
  • 默认值:true

压缩产物,目前默认仅在 build 阶段生效。源码中minify支持boolean | 'swc' | MinifyOptions(packages/ice/src/types/userConfig.ts),未显式配置时按context.command === 'build'决定是否压缩(packages/ice/src/config.ts);压缩由 TerserPlugin 承担,且支持通过minify: 'swc'切换到更快的 swc 压缩(packages/webpack-config/src/index.ts)。

dropLogLevel

  • 类型:boolean | DropType[] | DropType,其中DropType'trace' | 'debug' | 'log' | 'info' | 'warn' | 'error'
  • 默认值:false,不移除任何 console 代码

压缩代码时移除console.*相关代码。配置为true时移除所有console.*;只想移除部分(如console.logconsole.error)时:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ dropLogLevel: ['error', 'log'], }));

也可以按 console 等级批量移除:

// console 等级为 trace < debug < log < info < warn < error // 例如想要移除 trace、debug、log 时可以像下面这样配置 import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ dropLogLevel: 'log', }));

源码中实现了完整的等级换算(packages/ice/src/config.ts):true对应compress.drop_console: true;数组会映射为compress.pure_funcs中的console.xxx列表;字符串会按等级表(trace:0, debug:1, log:1, info:2, warn:3, error:4)取所有小于等于该等级的 console 方法。若传入非法字符串会打印警告。

codeSplitting 与 splitChunks(已废弃)

  • splitChunks(@deprecated):不再建议使用,能力由codeSplitting替代。默认会根据模块体积自动拆分 chunks,可能产生多个 bundle;若不希望产物出现过多 bundle 可设为false
  • codeSplitting:类型boolean | 'vendors' | 'page' | 'chunks' | 'page-vendors',默认值true

框架内置三种分包策略:

  • vendors:将异步 chunks 里的三方依赖统一打入vendor.js,避免重复、在依赖不变时有效利用缓存;缺陷是项目过大时单文件尺寸偏大;
  • page:所有路由级别组件按需加载,若需保留原splitChunks: false的效果可配置该策略;
  • page-vendors:在page策略基础上,将异步 chunks 里的三方依赖统一打入vendor.js,兼顾按需加载与缓存;
  • chunks:在路由级组件按需加载基础上,按模块体积自动拆分 chunks,为默认推荐策略。

若存在特殊场景需要关闭分包能力,可设为false。源码中策略的实际实现位于 packages/webpack-config/src/config/splitChunks.ts:chunks策略将reactreact-domreact-router等框架依赖整体打入frameworkchunk(priority 40),并将node_modules中体积大于 160000 字节的模块按内容 hash 拆分libchunk,同时限制maxInitialRequests: 25minSize: 20000vendors/page-vendors通过 cacheGroups 统一聚合三方依赖。另外,同时配置splitChunkscodeSplitting时会打印弃用警告,且codeSplitting优先(packages/ice/src/config.ts)。更完整的分包策略可参考代码分割进阶文档。

cssModules

  • 类型:{ localIdentName: string }
  • 默认值:{}

构建 CSS Modules 时定制 class 名称的生成规则(与 css-loader 的localIdentName一致)。例如配置'[hash:8]'只保留 hash 值,以精简 HTML 与 CSS 体积。默认情况下className="custom-head-tab-wrap"会被构建为class="custom-head-tab-wrap--rAEgGaqM",自定义后精简为class="rAEgGaqM"

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ cssModules: { localIdentName: '[hash:8]' }, }));

编译范围与转译配置

compileDependencies

  • 类型:array | boolean
  • 默认值:[](实际默认行为见下)

默认情况下,为保证 dev 阶段体验,node_modules下的文件不会进行编译;而 build 阶段为追求代码体积的极致优化与兼容性保证,会对node_modules内容也进行编译(源码中默认值即process.env.NODE_ENV !== 'development',见 packages/ice/src/config.ts)。

如果 dev 阶段需要额外编译一些依赖,而 build 阶段仍保持全量编译,可通过正则结合环境判断:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ compileDependencies: process.env.NODE_ENV === 'development' ? [/@alifd\/next/, /need-compile/] : true, }));

:::caution 如果 build 阶段仍然需要全量编译,请务必增加环境判断,避免误关 build 的依赖编译。 :::

如果希望 dev 和 build 阶段均编译node_modules,直接设为true

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ compileDependencies: true, }));

如果明确知道哪些依赖需要编译,也可以通过正则设置(对 dev 和 build 同时生效):

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ compileDependencies: [/@alifd\/next/, /need-compile/], }));

源码中字符串类型的依赖会自动加上node_modules前缀构成匹配正则;需注意在--speedup加速模式下不支持 RegExp 形式的配置(会直接报错),且 dev 阶段会通过config.compileIncludes传入编译 loader 的include规则。

postcss

  • 类型:ProcessOptions & { plugins?: (string | [string, Record<string, any>?])[] }
  • 默认值:{}

用于添加 postcss 自定义配置:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ postcss: { plugins: [ 'postcss-px-to-viewport-8-plugin', { // ... }, ], syntax: 'sugarss', } }));

ice.js 内置的 postcss 配置为:

{ "plugins": [ ["postcss-nested"], ["postcss-preset-env", { "stage": 3, "autoprefixer": { "flexbox": "no-2009", }, "features": { "custom-properties": false, }, }], ["postcss-plugin-rpx2vw"], ], }

如果需要完全重写 postcss 配置或修改内置配置,需要在项目根目录新增postcss.config.js,工程会检测到该文件后清空内置 postcss 配置(packages/shared-config/src/getPostcssOpts.ts):

module.exports = { plugins: [ [ 'postcss-preset-env', // 修改 postcss-preset-env 的选项 { stage: 2, } ] ], }

内置postcss-preset-env使用 Stage 3 特性并关闭了custom-properties(CSS 变量交给原生支持),同时默认启用 rpx2vw 转换(enableRpx2Vw,packages/webpack-config/src/index.ts);用户配置会与内置插件列表做数组合并而非整体覆盖。

polyfill

  • 类型:'usage' | 'entry' | false
  • 默认值:false

框架提供多种 polyfill 方式,可按实际情况选择:

  • usage:按开发者实际使用的语法自动引入对应 polyfill,适用于node_modules也参与编译的场景(一定程度上影响编译效率,且可能因三方依赖二次编译造成代码冗余);
  • entry:自动引入浏览器需要兼容的 polyfill,适用于node_modules依赖不参与编译的场景(可能引入大量未被使用的 polyfill)。

如果面向现代浏览器开发,大量 ES 语法无需 polyfill,推荐不开启polyfill配置。如果代码或三方依赖要求兼容到 IE 11 等浏览器,可以选择主动引入指定语法的 polyfill,或开启polyfill配置。

polyfill 生效依赖.browserslistrc声明的浏览器目标(packages/ice/src/types/userConfig.ts),与兼容性配置一节相互配合。

transform

  • 类型:(code: string, id: string) => string | { code: string; map?: SourceMap | null }
  • 默认值:undefined

通过transform配置实现代码转化:

import { defineConfig } from '@ice/app'; import { transformSync } from '@babel/core'; export default defineConfig(() => ({ transform: (originalCode, id) => { if (!id.includes('node_modules')) { // 借助 babel 编译 const { code, map } = transformSync(originalCode, { plugins: ['transform-decorators-legacy'], }); return { code, map }; } }, }));

ice.js 内置通过swc提升编译体验,如果在transform上过多依赖 babel 等工具,可能造成编译性能瓶颈。

源码中多次调用transform会被收集为数组逐个执行(packages/ice/src/config.ts),并在 webpack 中通过编译 loader 接入(packages/webpack-config/src/index.ts)。

syntaxFeatures

  • 类型:{ exportDefaultFrom: boolean; functionBind: boolean }
  • 默认值:undefined

ice.js 内置了大量 ES 语法支持。对于proposal-export-default-fromproposal-bind-operator这类提案进度较慢的语法并不推荐直接使用,如确需支持可显式开启:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ syntaxFeatures: { exportDefaultFrom: true, functionBind: true, }, }));

源码中开启后会注入 swc 编译器的 parser 选项(packages/ice/src/config.ts),且注释明确标注这两个语法不被 esbuild 支持(packages/ice/src/types/userConfig.ts)。

tsChecker

  • 类型:boolean
  • 默认值:false

默认关闭 TypeScript 类型检测,如需开启配置为true即可:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ tsChecker: true, }));

开启后底层通过 ForkTsCheckerPlugin 在独立进程做类型检查(packages/webpack-config/src/index.ts),默认只检测src目录下的源码(**/src/**/*,packages/ice/src/config.ts)。

eslint

  • 类型:boolean | object
  • 默认值:undefined

配置说明:

  • false:不检测 eslint 错误;
  • true:将 eslint 错误展示在预览页面上;
  • object:仅 Webpack 模式支持,表现等同于true,同时支持配置 eslint-webpack-plugin 的更多参数。

源码中的实现细节(packages/ice/src/config.ts):开启前会校验 eslint 主版本必须大于 7.0.0;默认检测js/ts/jsx/tsx扩展名;build 阶段failOnError: false(不因 lint 错误阻断构建),dev 阶段只 lint 变更文件(lintDirtyModulesOnly: true),从而兼顾体验与效率。

开发体验配置

proxy

  • 类型:object
  • 默认值:{}

配置 dev 开发阶段的代理功能,配置项与 webpackdevServer.proxy保持一致:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ proxy: { '/api': { target: 'http://jsonplaceholder.typicode.com/', changeOrigin: true, pathRewrite: { '^/api' : '' }, }, }, }));

该配置直接合并进 devServer 配置(packages/webpack-config/src/index.ts),仅在start命令下生效。

mock

  • 类型:{ exclude: string[] }
  • 默认值:{}

配置忽略 mock 的文件:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ mock: { // 忽略 mock 目录中 custom 目录下的文件以及 api.ts 文件 exclude: ["custom/**", "api.ts"] }, }));

配合默认的mock/目录约定(参考 examples/basic-project/mock 下的示例)与start命令的--mock参数一起使用。

渲染模式:SSR / SSG / Server 产物

ssr

  • 类型:boolean
  • 默认值:false

是否开启 SSR 能力。SSR(服务端渲染)在服务端运行 Node.js 程序动态生成 HTML,受设备性能与网络影响更小,可带来更好的性能与 SEO 体验;与 SSG 不同,ice.js 中 SSR 不是默认开启的,需要手动在ice.config.mts中设置ssr: true。更完整的配置与dataLoader/serverDataLoader的协作方式参考 SSR 文档。

ssg

  • 类型:boolean
  • 默认值:true

是否开启 SSG 能力。SSG(构建时渲染)在构建时就提前生成内容 HTML,ice.js 默认开启,不仅适用于静态站点,也适用于为普通 CSR 应用提前生成静态内容(如将不依赖数据的组件内容直接输出到 HTML)。更多细节(含staticDataLoader兜底数据)参考 SSG 文档。

server

  • 类型:{ format: 'esm' | 'cjs'; bundle: boolean; ignores: IgnorePattern[]; externals: string[]; onDemand: boolean }
  • 默认值:{ format: 'esm', bundle: false, ignores: [], externals: [], onDemand: false }

SSR / SSG 产物标准,推荐以 ESM 标准执行;如果想打包成一个 cjs 模块:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ server: { format: 'cjs', bundle: true, }, }));

注意源码中format: 'esm'bundle: true组合不被支持,会直接报错并退出(packages/ice/src/config.ts)。

通过ignores参数为 SSR / SSG 产物过滤指定文件:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ server: { ignores: [{ resourceRegExp: /^\.\/locale$/, contextRegExp: /moment$/, }] }, }));

其中:

  • resourceRegExp:对应文件的匹配路径;
  • contextRegExp(可选):对应文件内容的匹配规则。

通过externals参数在构建 Server 端产物时 external 指定内容:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ server: { externals: ['react', 'react-dom'] }, }));

通过onDemand参数,在执行 Server 端产物时按需构建所需模块,并提供体验良好的模块热更新服务:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ server: { onDemand: true, format: 'esm', }, }));

类型定义中还包含bundler: 'webpack' | 'esbuild'(默认 esbuild)与webpackConfig等扩展字段(packages/ice/src/types/userConfig.ts),说明服务端产物既支持 webpack 也支持更轻量的 esbuild 打包链路。

dataLoader

  • 类型:boolean | { fetcher: { packageName: string; method: string } }
  • 默认值:true

是否启用内置的数据预加载能力以及自定义发送者(fetcher)。开启后构建产物会为数据请求生成额外资源,源码中通过DataLoaderPlugin在 webpack 编译阶段收集路由组件的dataLoader导出并生成数据加载模块(packages/ice/src/bundler/webpack/getWebpackConfig.ts)。关闭方式:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ dataLoader: false, }));

完整的 dataLoader API 与 SSR/CSR 协作方式参考数据预加载文档(可对比 examples/with-data-loader 示例工程)。

路由定制:routes

  • 类型:{ ignoreFiles: string[]; defineRoutes: (route: DefineRouteFunction) => void; config?: RouteItem[] }
  • 默认值:{}

ignoreFiles

用于忽略src/pages下被处理成路由模块的文件,使用 glob 表达式(minimatch)对文件路径匹配:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ routes: { // 忽略 src/pages 下所有 components 目录 ignoreFiles: ['**/components/**'], }, }));

defineRoutes

对约定式路由不满足的场景,可通过该 API 自定义路由地址:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ routes: { defineRoutes: (route) => { // 将 /about-me 路由访问内容指定为 about.tsx // 第一个参数是路由地址 // 第二个参数是页面组件的相对地址(前面不能带 `/`),相对于 `src/pages` 目录 route('/about-me', 'about.tsx'); // 嵌套路由的场景需要使用第三个 callback 参数来定义嵌套路由 route('/', 'layout.tsx', () => { route('/product', 'products.tsx'); }); }, }, }));

:::caution 同一个路由组件只能分配一条路由规则,即同时执行以下语句时,仅生效后执行的逻辑:

route('/about-me', 'about.tsx'); route('/about-you', 'about.tsx');

:::

config

对于大量自定义或原配置式路由升级的项目,支持以config字段直接声明路由信息:

import { defineConfig } from '@ice/app'; export default defineConfig({ routes: { config: [ { path: 'rewrite', // 从 src/pages 开始计算路径,并且需要写后缀。 component: 'sales/layout.tsx', children: [ { path: '/favorites', component: 'sales/favorites.tsx', }, { path: 'overview', component: 'sales/overview.tsx', }, { path: 'recommends', component: 'sales/recommends.tsx', }, ], }, { path: '/', component: 'index.tsx', }, ], }, });

configcomponent路径从src/pages开始计算且必须带文件后缀。约定式路由与配置式路由的完整对比可参考路由文档与 examples/routes-config、examples/routes-generate 示例工程。

插件与底层扩展

plugins

  • 类型:PluginList<Config, OverwritePluginAPI>
  • 默认值:[]

添加插件:

import { defineConfig } from '@ice/app'; import customPlugin from './custom-plugin'; import myPlugin from '@ice/my-plugin'; export default defineConfig(() => ({ plugins: [ customPlugin(), myPlugin(), ], }));

ice.js 的插件体系基于build-scriptsPluginList类型(packages/ice/src/types/userConfig.ts),支持通过插件改写框架配置。仓库的 packages/plugin-* 目录下提供了 request、store、auth、i18n、icestark 等官方插件的完整实现,可作为编写自定义插件的参照;examples/basic-project/plugin.ts 展示了项目内自定义插件的接入方式。

webpack

:::tip ice.js 对 webpack 构建配置进行了定制,并借助 esbuild 等工具提升用户开发体验,直接修改 webpack 配置的方式并不推荐。 :::

  • 类型:(config: WebpackConfig, taskConfig: TaskConfig) => WebpackConfig
  • 默认值:true

ice.js 默认基于 webpack 5 构建,在上述构建配置无法满足需求时,可以定制 webpack 配置:

import { defineConfig } from '@ice/app'; import SpeedMeasurePlugin from 'speed-measure-webpack-plugin'; export default defineConfig(() => ({ webpack: (webpackConfig) => { if (process.env.NODE_ENV !== 'test') { // 添加 webpack 插件 webpackConfig.plugins?.push(new SpeedMeasurePlugin()); } return webpackConfig; }, }));

源码中每次调用webpack函数都会打印「不推荐直接配置 webpack」的警告(packages/ice/src/config.ts),随后将函数追加到configureWebpack管道中,最终与内置的 css/assets 配置一起按顺序执行(packages/webpack-config/src/index.ts)。

其他常用配置

sourceMap

  • 类型:boolean | string
  • 默认值:development模式下为'cheap-module-source-map'(支持通过false关闭,不支持设置为其他枚举值);production模式下默认false

源码中getDevtoolValuefalse映射为关闭 devtool,字符串原样透传,未配置时返回'source-map'(packages/shared-config/src/utils/getDevtool.ts)。

optimization

  • 类型:{ disableRouter: boolean; optimizePackageImport: boolean | string[] }
  • 默认值:{}

框架提供内置的优化能力:

  • disableRouter:默认false,如希望关闭路由能力可设为true,主要应用于不存在路由依赖的场景(如没有 SPA 页面跳转);
  • optimizePackageImport:默认false,开启后框架对已知三方依赖进行按需加载,进一步提升构建体验,内置三方依赖列表定义在 packages/ice/src/config.ts,包含@alifd/nextantdlodash-esramdadate-fnsahooks@mui/materialrecharts以及全部react-icons/*等主流库。

参考配置:

import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ optimization: { disableRouter: true, // optimizePackageImport 配置为 true 则使用内置的三方依赖列表,如果配置为数组则会在内置列表基础上追加 optimizePackageImport: ['@ice/components'], }, }));

需注意:optimizePackageImport仅在--speedup加速模式下生效,源码在非加速模式下会打印提示(packages/ice/src/config.ts);加速模式下不支持 RegExp 形式的compileDependencies

总结:配置优先级与生效命令

综合源码中的配置注册表(packages/ice/src/config.ts),可以归纳出 ice.js 构建配置的几个关键规律:

  1. 命令隔离publicPath仅在build生效、devPublicPath仅在start生效,proxy/mock属 dev 能力,minify默认只在 build 开启;
  2. 默认值即工程最佳实践ssg默认开启、ssr默认关闭、codeSplitting默认采用chunks策略、build 默认全量编译node_modules保证兼容性;
  3. 覆盖链路清晰:配置项 →userConfig注册表校验与归一 →Config中间对象 → webpack/编译插件执行。用户可通过 webpack 回调与 plugins 在最后一层接管,但官方明确不推荐直接改 webpack。

实际工程中可对照 examples/basic-project/ice.config.mts 查看一套包含 SSR、polyfill、alias、define、cssModules、eslint 等的完整生产配置,其余能力可在 examples 目录下的对应示例工程(如 examples/with-data-loader、examples/with-ssg、examples/with-suspense-ssr)中直接运行验证。

  • 前端
  • Web框架
  • SSR
  • 前端构建
  • 插件系统
  • 微前端
  • 跨平台

【免费下载链接】ice

🚀 ice.js: The Progressive App Framework Based On React(基于 React 的渐进式应用框架)

项目地址:https://gitcode.com/gh_mirrors/ice1/ice
点击查看免费下载
上一篇:解决Elasticsearch大整数精度丢失:elasticsearch-dump的big.js集成方案
下一篇:TypeScript 泛型完全指南:从 Queue 到便利泛型设计模式(typescript-book 实践篇)

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/21 19:20:16

3个坑让你少交学费,微星显卡超频源码深扒,面试必问

3个坑让你少交学费,微星显卡超频源码深扒,面试必问 配置环境就卡半天,是不是让你抓狂?很多开发者在折腾微星显卡超频时,光是在驱动和软件层面就耗费了大量时间,结果性能提升微乎其微,甚至导致系统蓝屏。这不仅是硬件折腾的问题,更是对底层驱动通信机制理解不足的表现。在技术面试中,关于GPU驱动通信、PCIe…

作者头像 李华
网站建设 2026/9/21 19:20:15

小写金额转换大写金额:3个致命坑点让新手避坑,大厂面试必考

小写金额转换大写金额:3个致命坑点让新手避坑,大厂面试必考 别再死记硬背了,看了一堆教程还是不会写项目,这才是最崩溃的。很多新人拿到这个需求,脑子一团浆糊,觉得不就是换个字符吗?其实这里藏着大厂筛选逻辑严密性的核心考点。今天就把【小写金额转换大写金额】这个高频题拆碎了讲,带你从原理到代码,彻底搞定它…

作者头像 李华
网站建设 2026/9/21 19:20:07

a股大赛图解原理:3步搞定证书下载避坑指南

a股大赛图解原理:3步搞定证书下载避坑指南 打开官方文档,满屏的“参赛资格”、“交易规则”、“结算机制”,是不是看得头大?很多人卡在这里,根本抓不住重点。别急,我们直接上 图解原理 ,把a股大赛的核心逻辑拆开揉碎,让你像看漫画一样看懂规则,不再被长文档劝退。…

作者头像 李华
网站建设 2026/9/21 19:20:04

e480笔记本性能优化实战:解决配置卡死与代码运行慢

e480笔记本性能优化实战:解决配置卡死与代码运行慢 刚把e480笔记本搬上工位,跑个Node.js环境安装脚本,进度条卡在20%整整十分钟。打开任务管理器,CPU占用率瞬间飙到100%,风扇狂转,机身烫手。这种“配置环境就卡半天”的体验,是许多开发者在低配硬件上的噩梦。别急着换电脑,很多时候不是硬…

作者头像 李华
网站建设 2026/9/21 19:19:27

面试必问有没有转向 最佳实践拆解

面试必问有没有转向 最佳实践拆解 面试被问底层原理答不上来,是开发者最尴尬的时刻。很多候选人背诵了标准答案,却经不起追问,导致面试直接凉凉。掌握有没有转向的最佳实践,能帮你从“背题”转向“懂题”,在技术深水区站稳脚跟。 考点梳理:到底在考什么…

作者头像 李华
网站建设 2026/9/21 19:19:16

古希腊电影源码解析:3步搞定项目落地,拒绝只懂皮毛

古希腊电影源码解析:3步搞定项目落地,拒绝只懂皮毛 看了一堆教程还是不会写项目?这是很多开发者卡在瓶颈期的真实写照。你背下了API,看懂了文档,但一上手写业务逻辑就抓瞎,感觉代码只是堆砌,没有灵魂。其实,问题不在于你学得不够多,而在于你缺乏对底层实现的 源码解析 。…

作者头像 李华