@deot/dev-dever 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -8,6 +8,8 @@ const devShared = require('@deot/dev-shared');
8
8
  const fs$1 = require('fs-extra');
9
9
  const vite = require('vite');
10
10
  const chalk = require('chalk');
11
+ const sharedVueConfig = require('@deot/dev-vue');
12
+ const sharedReactConfig = require('@deot/dev-react');
11
13
  const fs = require('node:fs');
12
14
  const ejs = require('ejs');
13
15
 
@@ -46,7 +48,7 @@ const walk = (dir) => {
46
48
  const paths = fullpath.split("/") || [];
47
49
  const stat = fs__namespace.statSync(fullpath);
48
50
  const extname = path__namespace.extname(fullpath);
49
- if (stat.isFile() && /\.(t|j)sx?$/.test(extname) && paths.length >= 2 && paths[paths.length - 2] === "examples") {
51
+ if (stat.isFile() && /\.((t|j)sx?|vue)$/.test(extname) && paths.length >= 2 && paths[paths.length - 2] === "examples") {
50
52
  const basename = path__namespace.basename(file, extname);
51
53
  let name = path__namespace.join(dir, basename).split("/");
52
54
  name.splice(name.length - 2, 1);
@@ -79,8 +81,7 @@ const run = (options) => devShared.Utils.autoCatch(async () => {
79
81
  if (options.dryRun)
80
82
  return devShared.Shell.spawn(`echo development`);
81
83
  const { cwd, workspace, packageOptionsMap, packageDirsMap } = locals;
82
- const { packageName } = options;
83
- const packageFolderName = devShared.Locals.getPackageFolderName(packageName);
84
+ const packageFolderName = devShared.Locals.getPackageFolderName(options.packageName);
84
85
  const packageOptions = packageOptionsMap[packageFolderName];
85
86
  const packageDir = packageDirsMap[packageFolderName];
86
87
  options.watch = true;
@@ -94,12 +95,6 @@ const run = (options) => devShared.Utils.autoCatch(async () => {
94
95
  delete options.workspace;
95
96
  delete options.packageName;
96
97
  let { entries, html } = get();
97
- process.env.DEV_OPTIONS = encodeURIComponent(JSON.stringify({
98
- ...options,
99
- workspace,
100
- entries,
101
- html
102
- }));
103
98
  if (!entries.length)
104
99
  return devShared.Shell.spawn(`echo no entry file found!`);
105
100
  let options$ = {
@@ -113,7 +108,20 @@ const run = (options) => devShared.Utils.autoCatch(async () => {
113
108
  options$.configFile = path__namespace.relative(cwd, path__namespace.resolve(cwd, "./dev.config.ts"));
114
109
  } else {
115
110
  options$.configFile = path__namespace.relative(cwd, path__namespace.resolve(dirname, "../shared.config.ts"));
111
+ const { vuePackage, reactPackage } = options;
112
+ if (vuePackage) {
113
+ options$ = vite.mergeConfig(sharedVueConfig, options$);
114
+ }
115
+ if (reactPackage) {
116
+ options$ = vite.mergeConfig(sharedReactConfig, options$);
117
+ }
116
118
  }
119
+ process.env.DEV_OPTIONS = encodeURIComponent(JSON.stringify({
120
+ ...options,
121
+ workspace,
122
+ entries,
123
+ html
124
+ }));
117
125
  const server = await vite.createServer(options$);
118
126
  const $server = await server.listen();
119
127
  const { local = [], network = [] } = $server.resolvedUrls || {};
package/dist/index.es.js CHANGED
@@ -2,8 +2,10 @@ import * as path from 'node:path';
2
2
  import { fileURLToPath } from 'node:url';
3
3
  import { Locals, Utils, Shell, Logger } from '@deot/dev-shared';
4
4
  import fs$1 from 'fs-extra';
5
- import { createServer } from 'vite';
5
+ import { mergeConfig, createServer } from 'vite';
6
6
  import chalk from 'chalk';
7
+ import sharedVueConfig from '@deot/dev-vue';
8
+ import sharedReactConfig from '@deot/dev-react';
7
9
  import * as fs from 'node:fs';
8
10
  import { render } from 'ejs';
9
11
 
@@ -22,7 +24,7 @@ const walk = (dir) => {
22
24
  const paths = fullpath.split("/") || [];
23
25
  const stat = fs.statSync(fullpath);
24
26
  const extname = path.extname(fullpath);
25
- if (stat.isFile() && /\.(t|j)sx?$/.test(extname) && paths.length >= 2 && paths[paths.length - 2] === "examples") {
27
+ if (stat.isFile() && /\.((t|j)sx?|vue)$/.test(extname) && paths.length >= 2 && paths[paths.length - 2] === "examples") {
26
28
  const basename = path.basename(file, extname);
27
29
  let name = path.join(dir, basename).split("/");
28
30
  name.splice(name.length - 2, 1);
@@ -55,8 +57,7 @@ const run = (options) => Utils.autoCatch(async () => {
55
57
  if (options.dryRun)
56
58
  return Shell.spawn(`echo development`);
57
59
  const { cwd, workspace, packageOptionsMap, packageDirsMap } = locals;
58
- const { packageName } = options;
59
- const packageFolderName = Locals.getPackageFolderName(packageName);
60
+ const packageFolderName = Locals.getPackageFolderName(options.packageName);
60
61
  const packageOptions = packageOptionsMap[packageFolderName];
61
62
  const packageDir = packageDirsMap[packageFolderName];
62
63
  options.watch = true;
@@ -70,12 +71,6 @@ const run = (options) => Utils.autoCatch(async () => {
70
71
  delete options.workspace;
71
72
  delete options.packageName;
72
73
  let { entries, html } = get();
73
- process.env.DEV_OPTIONS = encodeURIComponent(JSON.stringify({
74
- ...options,
75
- workspace,
76
- entries,
77
- html
78
- }));
79
74
  if (!entries.length)
80
75
  return Shell.spawn(`echo no entry file found!`);
81
76
  let options$ = {
@@ -89,7 +84,20 @@ const run = (options) => Utils.autoCatch(async () => {
89
84
  options$.configFile = path.relative(cwd, path.resolve(cwd, "./dev.config.ts"));
90
85
  } else {
91
86
  options$.configFile = path.relative(cwd, path.resolve(dirname, "../shared.config.ts"));
87
+ const { vuePackage, reactPackage } = options;
88
+ if (vuePackage) {
89
+ options$ = mergeConfig(sharedVueConfig, options$);
90
+ }
91
+ if (reactPackage) {
92
+ options$ = mergeConfig(sharedReactConfig, options$);
93
+ }
92
94
  }
95
+ process.env.DEV_OPTIONS = encodeURIComponent(JSON.stringify({
96
+ ...options,
97
+ workspace,
98
+ entries,
99
+ html
100
+ }));
93
101
  const server = await createServer(options$);
94
102
  const $server = await server.listen();
95
103
  const { local = [], network = [] } = $server.resolvedUrls || {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deot/dev-dever",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.es.js",
6
6
  "types": "dist/index.d.ts",
@@ -21,11 +21,14 @@
21
21
  "access": "public"
22
22
  },
23
23
  "dependencies": {
24
- "@deot/dev-shared": "^2.4.0",
24
+ "@deot/dev-react": "^2.5.0",
25
+ "@deot/dev-shared": "^2.5.0",
26
+ "@deot/dev-vue": "^2.5.0",
25
27
  "ejs": "^3.1.9",
26
28
  "vite": "^4.4.9"
27
29
  },
28
30
  "devDependencies": {
31
+ "@deot/dev-test": "^2.5.0",
29
32
  "cross-env": "^7.0.3"
30
33
  }
31
34
  }
package/shared.config.ts CHANGED
@@ -4,6 +4,14 @@ import { createRequire } from "node:module";
4
4
  import { defineConfig } from 'vitest/config';
5
5
  import type { UserConfig, ViteDevServer } from 'vite';
6
6
 
7
+ /**
8
+ * https://github.com/vuejs/core/issues/8303
9
+ * to fix error: ReferenceError: __name is not defined
10
+ */
11
+ let __defProp = Object.defineProperty;
12
+ let __name = (target: any, value: any) => __defProp(target, 'name', { value, configurable: true });
13
+ globalThis.__name = globalThis.__name || __name;
14
+
7
15
  const cwd = process.cwd();
8
16
 
9
17
  // devOptions
@@ -14,36 +22,7 @@ const { workspace, html } = devOptions;
14
22
  const replacement = (name: string) => path.resolve(cwd, `./packages/${name}/src`);
15
23
  const { name } = createRequire(cwd)(path.resolve(cwd, workspace ? `${workspace}/index` : '', 'package.json'));
16
24
 
17
- const getHtmlContent = async (url: string) => {
18
- let fullpath = path.join(cwd, workspace, url);
19
-
20
- if (
21
- /^\/?@vite/.test(url)
22
- || (fs.existsSync(fullpath) && fs.statSync(fullpath).isFile())
23
- ) {
24
- return;
25
- }
26
-
27
- if (url === '/') return html;
28
-
29
- const info = url.split('/').filter(i => !!i);
30
-
31
- const prefix = info.slice(0, -1);
32
- const entry = info.slice(-1)[0];
33
-
34
- if (prefix[prefix.length - 1] !== 'examples') {
35
- prefix.push('examples');
36
- }
37
-
38
- fullpath = path.join(
39
- cwd,
40
- workspace,
41
- prefix.join('/'),
42
- `${entry?.replace(/(\.html)$/, '.ts')}`
43
- );
44
-
45
- if (!fs.existsSync(fullpath)) return /\.[\s\S]+$/.test(entry) ? undefined : html;
46
-
25
+ const generateIndexHtml = (url: string, inject: string) => {
47
26
  let contents = '';
48
27
  contents += `<!DOCTYPE html>\n`;
49
28
  contents += `<html lang="en">\n`;
@@ -53,14 +32,74 @@ const getHtmlContent = async (url: string) => {
53
32
  contents += ` <title>demo-${url}</title>\n`;
54
33
  contents += ` </head>\n`;
55
34
  contents += ` <body>\n`;
35
+ contents += ` <div id="app"></div>\n`;
56
36
  contents += ` <script type="module">\n`;
57
- contents += ` import "/${path.relative(cwd, fullpath)}";\n`;
37
+ contents += inject;
38
+
58
39
  contents += ` </script>\n`;
59
40
  contents += ` </body>\n`;
60
41
  contents += `</html>\n`;
42
+
61
43
  return contents;
62
44
  };
63
45
 
46
+ const getVirtualHtml = async (url: string) => {
47
+ const info = url.split('/').filter(i => !!i);
48
+
49
+ const prefix = info.slice(0, -1);
50
+ const entry = info.slice(-1)[0];
51
+
52
+ if (prefix[prefix.length - 1] !== 'examples') {
53
+ prefix.push('examples');
54
+ }
55
+
56
+ if (workspace && prefix[0] !== workspace) {
57
+ prefix.unshift(workspace);
58
+ }
59
+
60
+ const dir = path.join(cwd, prefix.join('/'));
61
+ const isExist = (ext: string) => {
62
+ const fullpath = path.join(dir, `${entry.replace(/(.*)(\..*)$/, '$1') + ext}`);
63
+ return fs.existsSync(fullpath) ? fullpath : false;
64
+ };
65
+
66
+ const htmlFullpath = isExist('.html');
67
+ if (htmlFullpath) {
68
+ return fs.readFileSync(htmlFullpath).toString();
69
+ }
70
+
71
+ const tsFullpath = isExist('.ts');
72
+ if (tsFullpath) {
73
+ let inject = '';
74
+ inject += ` import "/${path.relative(cwd, tsFullpath)}";\n`;
75
+ return generateIndexHtml(url, inject);
76
+ }
77
+
78
+ const vueFullpath = isExist('.vue');
79
+ if (vueFullpath) {
80
+ let inject = '';
81
+ inject += ` import { createApp } from "vue"\n`;
82
+ inject += ` import App from "/${path.relative(cwd, vueFullpath)}";\n`;
83
+ inject += ` const app = createApp(App);\n`;
84
+ inject += ` app.mount("#app");\n`;
85
+ inject += ` typeof window !== "undefined" && (window.app = app);\n`;
86
+ return generateIndexHtml(url, inject);
87
+ }
88
+
89
+ const tsxFullpath = isExist('.tsx');
90
+ if (tsxFullpath) {
91
+ let inject = '';
92
+ inject += ` import React, { StrictMode } from 'react';`;
93
+ inject += ` import { createRoot } from 'react-dom/client';`;
94
+ inject += ` import App from "/${path.relative(cwd, tsxFullpath)}";\n`;
95
+ inject += ` const h = React.createElement\n`;
96
+ inject += ` const app = createRoot(document.getElementById('app'));\n`;
97
+ inject += ` app.render(h(StrictMode, {}, h(App)))\n`;
98
+
99
+ return generateIndexHtml(url, inject);
100
+ }
101
+ };
102
+
64
103
  export default defineConfig({
65
104
  resolve: workspace
66
105
  ? {
@@ -82,15 +121,35 @@ export default defineConfig({
82
121
  name: 'vite-plugin-virtual-html',
83
122
  configureServer(server: ViteDevServer) {
84
123
  server.middlewares.use(async (req, res, next) => {
85
- const url = req.url as string;
124
+ if (res.writableEnded) {
125
+ return next();
126
+ }
127
+ if (req.url!.includes('html-proxy&')) {
128
+ return next();
129
+ }
86
130
 
87
- const content = await getHtmlContent(url);
131
+ let url = req.url?.replace(/[?#].*$/s, '') || '';
132
+ if (url === '/') return res.end(html);
88
133
 
89
- if (!content) {
134
+ // 文件已存在,这样xxx.png可以被获取,真实路径的.ts,.html都可以被获取
135
+ if (fs.existsSync(path.join(cwd, url))) {
90
136
  return next();
91
137
  }
92
138
 
93
- res.end(content);
139
+ let vHtml = await getVirtualHtml(url);
140
+ if (
141
+ (url?.endsWith('.html') || vHtml)
142
+ && req.headers['sec-fetch-dest'] !== 'script'
143
+ ) {
144
+ if (!vHtml) {
145
+ return res.end(html);
146
+ }
147
+ vHtml = await server.transformIndexHtml(url, vHtml, req.originalUrl);
148
+ res.end(vHtml);
149
+ return;
150
+ }
151
+
152
+ next();
94
153
  });
95
154
  }
96
155
  }