Skip to content

Commit

Permalink
feat: support htmlGeneratingMode option
Browse files Browse the repository at this point in the history
  • Loading branch information
XGHeaven committed Dec 5, 2024
1 parent 6b3167a commit 588e09e
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/angry-carrots-occur.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ice/app': minor
---

feat: support htmlGeneratingMode option
1 change: 1 addition & 0 deletions .github/workflows/canary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: Publish canary
on:
push:
branches:
- feat/support-generating-mode # debug
- release/**

jobs:
Expand Down
5 changes: 4 additions & 1 deletion packages/ice/src/bundler/config/output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import injectInitialEntry from '../../utils/injectInitialEntry.js';
import { SERVER_OUTPUT_DIR } from '../../constant.js';
import { logger } from '../../utils/logger.js';
import type { BundlerOptions } from '../types.js';
import type { HtmlGeneratingMode } from '../../types/index.js';

export async function getOutputPaths(options: {
rootDir: string;
Expand All @@ -21,7 +22,7 @@ export async function getOutputPaths(options: {
}
}
if (serverEntry && userConfig.htmlGenerating) {
outputPaths = await buildCustomOutputs(rootDir, outputDir, serverEntry, bundleOptions);
outputPaths = await buildCustomOutputs(rootDir, outputDir, serverEntry, bundleOptions, userConfig.htmlGeneratingMode);

Check warning on line 25 in packages/ice/src/bundler/config/output.ts

View workflow job for this annotation

GitHub Actions / build (16.x, ubuntu-latest)

This line has a length of 122. Maximum allowed is 120

Check warning on line 25 in packages/ice/src/bundler/config/output.ts

View workflow job for this annotation

GitHub Actions / build (16.x, windows-latest)

This line has a length of 122. Maximum allowed is 120

Check warning on line 25 in packages/ice/src/bundler/config/output.ts

View workflow job for this annotation

GitHub Actions / build (18.x, ubuntu-latest)

This line has a length of 122. Maximum allowed is 120

Check warning on line 25 in packages/ice/src/bundler/config/output.ts

View workflow job for this annotation

GitHub Actions / build (18.x, windows-latest)

This line has a length of 122. Maximum allowed is 120
}
return outputPaths;
}
Expand All @@ -37,6 +38,7 @@ async function buildCustomOutputs(
outputDir: string,
serverEntry: string,
bundleOptions: Pick<BundlerOptions, 'userConfig' | 'appConfig' | 'routeManifest'>,
generatingMode?: HtmlGeneratingMode,
) {
const { userConfig, appConfig, routeManifest } = bundleOptions;
const { ssg } = userConfig;
Expand All @@ -52,6 +54,7 @@ async function buildCustomOutputs(
renderMode: ssg ? 'SSG' : undefined,
routeType: appConfig?.router?.type,
routeManifest,
generatingMode,
});
if (routeType === 'memory' && userConfig?.routes?.injectInitialEntry) {
injectInitialEntry(routeManifest, outputDir);
Expand Down
5 changes: 5 additions & 0 deletions packages/ice/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,11 @@ const userConfig = [
validation: 'boolean',
defaultValue: true,
},
{
name: 'htmlGeneratingMode',
validation: 'string',
defaultValue: 'cleanUrl',
},
];

const cliOption = [
Expand Down
11 changes: 11 additions & 0 deletions packages/ice/src/types/userConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ interface Fetcher {
method?: string;
}

export type HtmlGeneratingMode = 'cleanUrl' | 'compat';

export interface UserConfig {
/**
* Feature polyfill for legacy browsers, which can not polyfilled by core-js.
Expand Down Expand Up @@ -179,6 +181,15 @@ export interface UserConfig {
* @see https://v3.ice.work/docs/guide/basic/config#htmlgenerating
*/
htmlGenerating?: boolean;
/**
* Control how file structure to generation html.
* Route: '/' '/foo' '/foo/bar'
* `cleanUrl`: '/index.html' '/foo.html' '/foo/bar.html'
* `compat`: '/index.html' '/foo/index.html' '/foo/bar/index.html'
* @see https://v3.ice.work/docs/guide/basic/config#htmlgeneratingmode
* @default 'cleanUrl'
*/
htmlGeneratingMode?: HtmlGeneratingMode;
/**
* Choose a style of souce mapping to enhance the debugging process.
* @see https://v3.ice.work/docs/guide/basic/config#sourcemap
Expand Down
19 changes: 15 additions & 4 deletions packages/ice/src/utils/generateEntry.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as path from 'path';
import fse from 'fs-extra';
import type { ServerContext, RenderMode, AppConfig } from '@ice/runtime';
import type { HtmlGeneratingMode } from '../types/index.js';
import dynamicImport from './dynamicImport.js';
import { logger } from './logger.js';
import type RouteManifest from './routeManifest.js';
Expand All @@ -12,6 +13,7 @@ interface Options {
documentOnly: boolean;
routeType: AppConfig['router']['type'];
renderMode?: RenderMode;
generatingMode?: HtmlGeneratingMode;
routeManifest: RouteManifest;
}

Expand All @@ -28,6 +30,7 @@ export default async function generateEntry(options: Options): Promise<EntryResu
renderMode,
routeType,
routeManifest,
generatingMode,
} = options;

let serverEntry: string;
Expand All @@ -48,7 +51,7 @@ export default async function generateEntry(options: Options): Promise<EntryResu
} = await renderEntry({ routePath, serverEntry, documentOnly, renderMode });
const generateOptions = { rootDir, routePath, outputDir };
if (htmlOutput) {
const path = await generateFilePath({ ...generateOptions, type: 'html' });
const path = await generateFilePath({ ...generateOptions, type: 'html', generatingMode });
await writeFile(
path,
htmlOutput,
Expand All @@ -72,8 +75,14 @@ export function escapeRoutePath(str: string) {
return str.replace(/\/(:|\*)/g, '/$');
}

function formatFilePath(routePath: string, type: 'js' | 'html' | 'js.map'): string {
return routePath === '/' ? `index.${type}` : `${escapeRoutePath(routePath)}.${type}`;
function formatFilePath(routePath: string, type: 'js' | 'html' | 'js.map', generatingMode?: HtmlGeneratingMode): string {
if (routePath === '/') {
return `index.${type}`;
}
if (type === 'html' && generatingMode === 'compat') {
return `${escapeRoutePath(routePath)}/index.${type}`;
}
return `${escapeRoutePath(routePath)}.${type}`;
}

async function generateFilePath(
Expand All @@ -82,14 +91,16 @@ async function generateFilePath(
routePath,
outputDir,
type,
generatingMode,
}: {
rootDir: string;
routePath: string;
outputDir: string;
type: 'js' | 'html' | 'js.map' ;
generatingMode?: HtmlGeneratingMode;
},
) {
const fileName = formatFilePath(routePath, type);
const fileName = formatFilePath(routePath, type, generatingMode);
if (fse.existsSync(path.join(rootDir, 'public', fileName))) {
logger.warn(`${fileName} is overwrite by framework, rename file name if it is necessary.`);
}
Expand Down
15 changes: 15 additions & 0 deletions website/docs/guide/basic/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,21 @@ export default defineConfig(() => ({

如果产物不想生成 html,可以设置为 `false`,在 SSG 开启的情况下,强制关闭 html 生成,将导致 SSG 失效。

### htmlGeneratingMode

- 类型: `'cleanUrl' | 'compat'`
- 默认值 `'cleanUrl'`

当开启 html 生成的时候,可以用来配置生成目录的规则,避免在某些服务器下出现非首页内容 404 的情况。目前主要由两种,分别是:

- `cleanUrl` 生成的文件路径和路由一致,只不过多了 `.html`。通常用于支持此模式的现代服务器
- `compat` 生成兼容模式的路径文件,通常用于一些只能省略 `index.html` 的服务器

| 路径 | `/` | `/foo` | `/foo/bar` |
|------------|---------------|-------------------|-----------------------|
| `cleanUrl` | `/index.html` | `/foo.html` | `/foo/bar.html` |
| `compat` | `/index.html` | `/foo/index.html` | `/foo/bar/index.html` |

### plugins

- 类型:`PluginList<Config, OverwritePluginAPI>`
Expand Down

0 comments on commit 588e09e

Please sign in to comment.