Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions docs/docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ page-plugin settings.
| `routing` | Enable file-based pages and select SPA or MPA | Not enabled until declared |
| `conventions` | Enable all framework file conventions | `true` |
| `dev` | Browser development server | Port `3000` |
| `logging` | Development logging, including browser-to-terminal forwarding | Browser errors forwarded |
| `server` | Server runtime, build resolution, and development server | Base path `/__evjs`, dev port `3001` |
| `transport` | Browser-to-server origin | Same origin |
| `target` | Production Android and iOS compatibility target | Bundler default |
Expand Down Expand Up @@ -129,6 +130,22 @@ A proxy rule accepts `context`, `target`, optional `pathRewrite`,
client HTTPS. Select the Webpack adapter when the client dev server requires a
custom key/certificate pair.

### `logging`

`logging.browserToTerminal` follows the Next.js-compatible level contract and
only affects `ev dev` with the Utoopack adapter:

| Value | Browser output forwarded to the terminal |
| --- | --- |
| `"error"` | Errors and unhandled rejections (default) |
| `"warn"` | Warnings plus errors |
| `true` | All standard console levels |
| `false` | Nothing |

Set top-level `logging: false` to disable configurable logging. Essential CLI
lifecycle output and fatal diagnostics remain enabled. The Webpack adapter does
not currently implement browser log forwarding.

### `server.dev`

| Field | Type | Default |
Expand Down
22 changes: 22 additions & 0 deletions docs/docs/dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ the same project directory at a time; stop an existing `dev`, `prepare`, or
import { defineConfig } from "@evjs/ev";

export default defineConfig({
logging: {
browserToTerminal: "error", // Browser errors -> terminal (default)
},
dev: {
port: 4000,
},
Expand Down Expand Up @@ -172,6 +175,25 @@ evjs core does not reserve shortcut keys; installed plugins define the keys
they use. Plugin authors can find the authoring contract in
[Plugin Hooks](./plugin-hooks).

## Browser logs in the terminal

The Utoopack development server forwards browser errors to the terminal by
default. Configure the Next.js-compatible forwarding level in `ev.config.ts`:

```ts
export default defineConfig({
logging: {
browserToTerminal: "warn",
},
});
```

Use `"error"` for errors only (the default), `"warn"` for warnings and errors,
`true` for all standard console levels, or `false` to disable forwarding.
Forwarded lines use a `[browser]` prefix and include source-mapped application
locations when available. This is development-only and is not a production log
collector. The Webpack adapter does not currently implement this option.

## Test server paths directly

The default server runtime prefix is `/__evjs`. Server-function, PPR, and RSC
Expand Down
15 changes: 15 additions & 0 deletions docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default defineConfig({
| `routing` | 启用文件页面并选择 SPA 或 MPA | 声明后才启用 |
| `conventions` | 启用全部框架文件约定 | `true` |
| `dev` | 浏览器开发服务器 | 端口 `3000` |
| `logging` | 开发日志,包括浏览器到终端转发 | 默认转发浏览器错误 |
| `server` | 服务端运行时、构建解析与开发服务器 | 基础路径 `/__evjs`,开发端口 `3001` |
| `transport` | 浏览器到服务端的来源 | 同源 |
| `target` | 生产 Android 与 iOS 兼容目标 | 构建器默认值 |
Expand Down Expand Up @@ -121,6 +122,20 @@ export default defineConfig({

代理规则支持 `context`、`target`,以及可选 `pathRewrite`、`changeOrigin` 和 `secure`。默认 Utoopack 适配器支持布尔形式的客户端 HTTPS;需要自定义客户端证书时选择 Webpack 适配器。

### `logging`

`logging.browserToTerminal` 使用与 Next.js 兼容的级别契约,仅影响采用
Utoopack 适配器的 `ev dev`:

| 值 | 转发到终端的浏览器输出 |
| --- | --- |
| `"error"` | 错误与未处理的 Promise rejection(默认值) |
| `"warn"` | 警告与错误 |
| `true` | 全部标准 console 级别 |
| `false` | 不转发 |

设置顶层 `logging: false` 可关闭可配置日志。必要的 CLI 生命周期输出与致命诊断仍会保留。Webpack 适配器目前尚未实现浏览器日志转发。

### `server.dev`

| 字段 | 类型 | 默认值 |
Expand Down
17 changes: 17 additions & 0 deletions docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ flowchart LR
import { defineConfig } from "@evjs/ev";

export default defineConfig({
logging: {
browserToTerminal: "error", // 浏览器错误 -> 终端(默认值)
},
dev: {
port: 4000,
},
Expand Down Expand Up @@ -150,6 +153,20 @@ ev dev --no-shortcuts

evjs 核心不占用任何按键,具体快捷键由已安装插件定义。插件作者可以在[插件生命周期钩子](./plugin-hooks)查看契约。

## 在终端查看浏览器日志

Utoopack 开发服务器默认会将浏览器错误转发到终端。在 `ev.config.ts` 中使用与 Next.js 兼容的选项配置转发级别:

```ts
export default defineConfig({
logging: {
browserToTerminal: "warn",
},
});
```

`"error"` 仅转发错误(默认值),`"warn"` 转发警告与错误,`true` 转发全部标准 console 级别,`false` 关闭转发。转发行以 `[browser]` 为前缀,并在可用时包含 source map 还原后的应用源码位置。该能力仅用于开发,并非生产日志采集器。Webpack 适配器目前尚未实现此选项。

## 直接测试服务端路径

默认服务端运行时前缀是 `/__evjs`。只有应用使用对应能力时才会创建服务端函数、PPR 与 RSC 路径。这个前缀不是服务端通配命名空间,因此无关客户端路由仍然可用。
Expand Down
25 changes: 18 additions & 7 deletions packages/bundler-utoopack/src/adapter/config/create-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
resolveBuildOutputPaths,
SERVER_FUNCTION_TRANSFORM_RUNTIME,
} from "@evjs/ev/_internal/build";
import type { ResolvedConfig } from "@evjs/ev/config";
import type { BrowserToTerminal, ResolvedConfig } from "@evjs/ev/config";
import type { ConfigureBundlerContext, PluginHooks } from "@evjs/ev/plugin";
import { pageRoutePathToRegExp } from "@evjs/shared";
import type { BuildPlan } from "@evjs/shared/manifest";
Expand All @@ -41,6 +41,12 @@ const lessImplementation = require.resolve("less");
const lessLoader = require.resolve("less-loader");
const spaHistoryFallbackRuleIndexes = new WeakMap<ConfigComplete, number>();

type UtoopackDevServerConfigWithBrowserLogs = NonNullable<
ConfigComplete["devServer"]
> & {
browserToTerminal?: BrowserToTerminal;
};

export function getSpaHistoryFallbackRuleIndex(
config: ConfigComplete,
): number | undefined {
Expand Down Expand Up @@ -118,6 +124,16 @@ export async function createUtoopackConfig(
const outputPaths = resolveBuildOutputPaths(cwd, plan);
await assertSafeBuildOutputPaths(cwd, outputPaths);

const devServerConfig: UtoopackDevServerConfigWithBrowserLogs = {
hot: true,
port: config.dev.port,
https: config.dev.https !== false,
proxy: devProxy,
...(!isProduction
? { browserToTerminal: config.logging.browserToTerminal }
: {}),
};

const utoopackConfig: ConfigComplete = {
mode,
...(isProduction && config.target !== undefined && clientEntries.length > 0
Expand Down Expand Up @@ -209,12 +225,7 @@ export async function createUtoopackConfig(
: {}),

// Dev server configuration
devServer: {
hot: true,
port: config.dev.port,
https: config.dev.https !== false,
proxy: devProxy,
},
devServer: devServerConfig,
};
const frameworkExpectation =
snapshotUtoopackFrameworkExpectation(utoopackConfig);
Expand Down
28 changes: 28 additions & 0 deletions packages/bundler-utoopack/tests/adapter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import type { ConfigComplete } from "@utoo/pack";
import { afterEach, describe, expect, it, vi } from "vitest";
import { withPageRoutingDefaults } from "../../ev/esm/_internal/build/discovery/convention-config.js";
import { createClientRuntime } from "../../ev/src/_internal/build/output/framework-runtime.js";
import { createUtoopackConfig } from "../src/adapter/config/create-config.js";
import {
utoopackAdapter,
__testing as utoopackAdapterTesting,
Expand Down Expand Up @@ -459,6 +460,33 @@ describe("utoopackAdapter output safety", () => {
});
});

describe("utoopackAdapter browser log forwarding config", () => {
it("maps the resolved level into development config only", async () => {
const cwd = await makeProject();
const config = await resolveProjectConfig(cwd, {
logging: { browserToTerminal: "warn" },
});
const { plan } = await createBuildContext(config, cwd);

const development = await createUtoopackConfig(config, plan, cwd, []);
expect(Reflect.get(development.devServer ?? {}, "browserToTerminal")).toBe(
"warn",
);

const productionPlan = structuredClone(plan);
productionPlan.mode = "production";
const production = await createUtoopackConfig(
config,
productionPlan,
cwd,
[],
);
expect(Object.hasOwn(production.devServer ?? {}, "browserToTerminal")).toBe(
false,
);
});
});

describe("utoopackAdapter dev", () => {
it("waits for readable stats until the session is aborted", async () => {
const cwd = await makeProject();
Expand Down
3 changes: 3 additions & 0 deletions packages/bundler-utoopack/tests/create-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ describe("createUtoopackConfig", () => {
proxy: [],
cliShortcuts: true,
},
logging: {
browserToTerminal: "error",
},
server: {
basePath: "/__evjs",
runtime: {
Expand Down
3 changes: 3 additions & 0 deletions packages/bundler-utoopack/tests/multi-server-entry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ function createResolvedConfig(): Parameters<typeof createUtoopackConfig>[0] {
proxy: [],
cliShortcuts: true,
},
logging: {
browserToTerminal: "error",
},
server: {
basePath: "/__evjs",
runtime: {
Expand Down
3 changes: 3 additions & 0 deletions packages/bundler-webpack/tests/create-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1222,6 +1222,9 @@ function createResolvedConfig(
proxy: [],
cliShortcuts: true,
},
logging: {
browserToTerminal: "error",
},
output: {
client: "dist/client",
server: "dist/server",
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/tests/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ describe("CONFIG_DEFAULTS", () => {
expect(CONFIG_DEFAULTS.serverPort).toBe(3001);
expect(CONFIG_DEFAULTS.serverBasePath).toBe("/__evjs");
expect(CONFIG_DEFAULTS.crossOriginLoading).toBe("anonymous");
expect(CONFIG_DEFAULTS.browserToTerminal).toBe("error");
});

it("is readonly", () => {
Expand All @@ -61,6 +62,7 @@ describe("CONFIG_DEFAULTS", () => {
outputServerDir: "dist/server",
pageRoot: "./src/pages",
mount: "#app",
browserToTerminal: "error",
});
});
});
3 changes: 3 additions & 0 deletions packages/ev/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export {
type BrowserToTerminal,
type ClientTarget,
CONFIG_DEFAULTS,
type Config,
Expand All @@ -14,6 +15,7 @@ export {
definePageConfig,
type ExtractInstalledPlugin,
type InstalledPluginRegistry,
type LoggingConfig,
merge,
type OutputConfig,
type PageAnchorMetadata,
Expand All @@ -32,6 +34,7 @@ export {
type ResolvedConfigRouteApplicationDocument,
type ResolvedDevConfig,
type ResolvedFrameworkConfig,
type ResolvedLoggingConfig,
type ResolvedOutputConfig,
type ResolvedPageRoutingConfig,
type ResolvedPolyfillConfig,
Expand Down
Loading