Skip to content

Commit

Permalink
feat: support theme component hmr
Browse files Browse the repository at this point in the history
  • Loading branch information
sanyuan0704 committed Aug 28, 2022
1 parent 1e3d78f commit 66f34c0
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 30 deletions.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -9,3 +9,5 @@
- 开发阶段 CSR 正常运行

- 生产环境构建 SSR 产物

- 支持主题组件 HMR
2 changes: 2 additions & 0 deletions src/node/constants/index.ts
Expand Up @@ -19,3 +19,5 @@ export const THEME_PATH = join(
export const TEMP_PATH = 'node_modules/.island';

export const SERVER_OUTPUT_PATH = join(TEMP_PATH, 'ssr-entry.mjs');

export const DEFAULT_HTML_PATH = join(__dirname, '../../../template.html');
82 changes: 52 additions & 30 deletions src/node/plugin.ts
@@ -1,6 +1,13 @@
import { Plugin } from 'vite';
import { CLIENT_ENTRY_PATH, THEME_PATH } from './constants';
import {
CLIENT_ENTRY_PATH,
DEFAULT_HTML_PATH,
isProduction,
THEME_PATH
} from './constants';
import reactPlugin from '@vitejs/plugin-react';
import fs from 'fs-extra';
import { createContext } from 'react';

export function createIslandPlugins() {
const islandPlugin: Plugin = {
Expand All @@ -14,41 +21,56 @@ export function createIslandPlugins() {
}
};
},
transformIndexHtml(html) {
if (isProduction()) {
return html;
}
// Insert client entry script in development
// And in production, we will insert it in ssr render
return {
html,
tags: [
{
tag: 'script',
attrs: {
type: 'module',
src: `/@fs/${CLIENT_ENTRY_PATH}`
},
injectTo: 'body'
}
]
};
},
configureServer(server) {
return () => {
server.middlewares.use((req, res, next) => {
if (req.url?.endsWith('.html')) {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
res.end(`
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="">
</head>
<body>
<div id="root"></div>
<script type="module" src="/@fs/${CLIENT_ENTRY_PATH}"></script>
</body>
</html>`);
return;
server.middlewares.use(async (req, res, next) => {
if (res.writableEnded) {
return next();
}
if (req.url?.replace(/\?.*/, '').endsWith('.html')) {
let html = fs.readFileSync(DEFAULT_HTML_PATH, 'utf8');

next();
try {
html = await server.transformIndexHtml(
req.url,
html,
req.originalUrl
);
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
res.end(html);
} catch (e) {
return next(e);
}
}
});
};
}
};
const reactImportPlugin: Plugin = {
name: 'internal:react-import',
transform(code, id) {
if (id.endsWith('.jsx') || id.endsWith('.tsx')) {
return `import React from 'react';\n${code}`;
}
}
};
return [islandPlugin];
return [
islandPlugin,
reactPlugin({
jsxRuntime: 'classic'
})
];
}
15 changes: 15 additions & 0 deletions template.html
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>

<head>
<title></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="">
</head>

<body>
<div id="root"></div>
</body>

</html>

0 comments on commit 66f34c0

Please sign in to comment.