@grafana/create-plugin 7.17.0 → 7.19.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/CHANGELOG.md +19 -0
- package/dist/codemods/additions/additions.js +7 -0
- package/dist/codemods/additions/prompts/rspack.md +120 -0
- package/dist/codemods/additions/scripts/docs.js +2 -2
- package/dist/codemods/additions/scripts/rspack.js +341 -0
- package/dist/codemods/agentic/prompts.js +1 -1
- package/dist/codemods/migrations/migrations.js +6 -0
- package/dist/codemods/migrations/scripts/020-rename-rspack-feature-flag.js +8 -0
- package/dist/codemods/utils.rspack.js +38 -0
- package/dist/commands/generate.command.js +1 -9
- package/dist/constants.js +0 -1
- package/dist/utils/utils.templates.js +4 -4
- package/package.json +1 -1
- package/src/codemods/additions/additions.test.ts +9 -0
- package/src/codemods/additions/additions.ts +7 -0
- package/src/codemods/additions/prompts/rspack.md +120 -0
- package/src/codemods/additions/scripts/docs.test.ts +4 -4
- package/src/codemods/additions/scripts/docs.ts +2 -2
- package/src/codemods/additions/scripts/rspack.test.ts +852 -0
- package/src/codemods/additions/scripts/rspack.ts +453 -0
- package/src/codemods/agentic/prompts.test.ts +11 -2
- package/src/codemods/agentic/prompts.ts +1 -1
- package/src/codemods/migrations/migrations.ts +7 -0
- package/src/codemods/migrations/scripts/020-rename-rspack-feature-flag.test.ts +94 -0
- package/src/codemods/migrations/scripts/020-rename-rspack-feature-flag.ts +8 -0
- package/src/codemods/utils.rspack.ts +58 -0
- package/src/codemods/utils.test.ts +5 -2
- package/src/commands/generate.command.ts +2 -10
- package/src/constants.ts +0 -1
- package/src/types.ts +1 -1
- package/src/utils/tests/utils.config.test.ts +10 -0
- package/src/utils/utils.config.ts +2 -1
- package/src/utils/utils.templates.ts +4 -4
- package/templates/common/.config/AGENTS/instructions.md +2 -2
- package/templates/common/.config/README.md +56 -0
- package/templates/common/.config/bundler/externals.ts +3 -3
- package/templates/common/.config/rspack/DiagnosticsRspackPlugin.ts +29 -0
- package/templates/common/.config/rspack/LicenseRspackPlugin.ts +43 -0
- package/templates/common/.config/rspack/LiveReloadRspackPlugin.ts +95 -0
- package/templates/common/.config/rspack/PluginCssRspackPlugin.ts +103 -0
- package/templates/common/.config/rspack/rspack.config.ts +79 -48
- package/templates/common/.cprc.json +1 -2
- package/templates/common/_package.json +22 -22
- package/templates/common/.config/rspack/liveReloadPlugin.ts +0 -133
|
@@ -5,24 +5,34 @@
|
|
|
5
5
|
* https://grafana.com/developers/plugin-tools/how-to-guides/extend-configurations#extend-the-webpack-config
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import
|
|
9
|
-
|
|
8
|
+
import {
|
|
9
|
+
BannerPlugin,
|
|
10
|
+
Compilation,
|
|
11
|
+
CopyRspackPlugin,
|
|
12
|
+
LightningCssMinimizerRspackPlugin,
|
|
13
|
+
SubresourceIntegrityPlugin,
|
|
14
|
+
SwcJsMinimizerRspackPlugin,
|
|
15
|
+
type Configuration,
|
|
16
|
+
} from '@rspack/core';
|
|
10
17
|
import { TsCheckerRspackPlugin } from 'ts-checker-rspack-plugin';
|
|
11
18
|
import path from 'path';
|
|
12
19
|
import ReplaceInFileWebpackPlugin from 'replace-in-file-webpack-plugin';
|
|
13
|
-
import TerserPlugin from 'terser-webpack-plugin';
|
|
14
20
|
import { RspackVirtualModulePlugin } from 'rspack-plugin-virtual-module';
|
|
15
21
|
|
|
16
|
-
import RspackLiveReloadPlugin from './
|
|
22
|
+
import RspackLiveReloadPlugin from './LiveReloadRspackPlugin.ts';
|
|
17
23
|
import { BuildModeRspackPlugin } from './BuildModeRspackPlugin.ts';
|
|
24
|
+
import { LicenseRspackPlugin } from './LicenseRspackPlugin.ts';
|
|
25
|
+
import DiagnosticsRspackPlugin from './DiagnosticsRspackPlugin.ts';
|
|
26
|
+
import { PluginCssRspackPlugin } from './PluginCssRspackPlugin.ts';
|
|
18
27
|
import { DIST_DIR, SOURCE_DIR } from '../bundler/constants.ts';
|
|
19
28
|
import { getCPConfigVersion, getEntries, getPackageJson, getPluginJson, isWSL } from '../bundler/utils.ts';
|
|
20
29
|
import { externals } from '../bundler/externals.ts';
|
|
21
30
|
import { copyFilePatterns } from '../bundler/copyFiles.ts';
|
|
22
31
|
|
|
23
|
-
const { SubresourceIntegrityPlugin } = rspack.experiments;
|
|
24
32
|
const pluginJson = getPluginJson();
|
|
33
|
+
const pluginId = pluginJson.id;
|
|
25
34
|
const cpVersion = getCPConfigVersion();
|
|
35
|
+
const pluginVersion = getPackageJson().version;
|
|
26
36
|
const virtualPublicPath = new RspackVirtualModulePlugin({
|
|
27
37
|
'grafana-public-path': `
|
|
28
38
|
import amdMetaModule from 'amd-module';
|
|
@@ -30,19 +40,29 @@ import amdMetaModule from 'amd-module';
|
|
|
30
40
|
__webpack_public_path__ =
|
|
31
41
|
amdMetaModule && amdMetaModule.uri
|
|
32
42
|
? amdMetaModule.uri.slice(0, amdMetaModule.uri.lastIndexOf('/') + 1)
|
|
33
|
-
: 'public/plugins/${
|
|
43
|
+
: 'public/plugins/${pluginId}/';
|
|
34
44
|
`,
|
|
35
45
|
});
|
|
36
46
|
|
|
37
|
-
|
|
47
|
+
export type Env = {
|
|
48
|
+
[key: string]: true | string | Env;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const config = async (env: Env): Promise<Configuration> => {
|
|
38
52
|
const baseConfig: Configuration = {
|
|
39
53
|
context: path.join(process.cwd(), SOURCE_DIR),
|
|
40
54
|
|
|
41
55
|
devtool: env.production ? 'source-map' : 'eval-source-map',
|
|
42
56
|
|
|
43
|
-
|
|
57
|
+
// grafana-public-path sets the public path first. grafana-plugin-css adds ./module.css to the define() dependencies
|
|
58
|
+
entry: Object.fromEntries(
|
|
59
|
+
Object.entries(await getEntries()).map(([name, entryPath]) => [
|
|
60
|
+
name,
|
|
61
|
+
['grafana-public-path', 'grafana-plugin-css', entryPath],
|
|
62
|
+
])
|
|
63
|
+
),
|
|
44
64
|
|
|
45
|
-
externals,
|
|
65
|
+
externals: [...externals, { 'grafana-plugin-css': './module.css' }],
|
|
46
66
|
|
|
47
67
|
// Support WebAssembly according to latest spec - makes WebAssembly module async
|
|
48
68
|
experiments: {
|
|
@@ -52,19 +72,15 @@ const config = async (env): Promise<Configuration> => {
|
|
|
52
72
|
mode: env.production ? 'production' : 'development',
|
|
53
73
|
|
|
54
74
|
module: {
|
|
75
|
+
parser: {
|
|
76
|
+
// keeps default imports of CSS modules working: `import styles from './x.module.css'`
|
|
77
|
+
'css/auto': { namedExports: false },
|
|
78
|
+
},
|
|
79
|
+
generator: {
|
|
80
|
+
// class names of CSS modules start with the plugin id
|
|
81
|
+
'css/auto': { localIdentName: '[uniqueName]-[local]-[hash:6]' },
|
|
82
|
+
},
|
|
55
83
|
rules: [
|
|
56
|
-
// This must come first in the rules array otherwise it breaks sourcemaps.
|
|
57
|
-
{
|
|
58
|
-
test: /src\/(?:.*\/)?module\.tsx?$/,
|
|
59
|
-
use: [
|
|
60
|
-
{
|
|
61
|
-
loader: 'imports-loader',
|
|
62
|
-
options: {
|
|
63
|
-
imports: `side-effects grafana-public-path`,
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
},
|
|
68
84
|
{
|
|
69
85
|
exclude: /(node_modules)/,
|
|
70
86
|
test: /\.[tj]sx?$/,
|
|
@@ -91,11 +107,12 @@ const config = async (env): Promise<Configuration> => {
|
|
|
91
107
|
},
|
|
92
108
|
{
|
|
93
109
|
test: /\.css$/,
|
|
94
|
-
|
|
110
|
+
type: 'css/auto',
|
|
95
111
|
},
|
|
96
112
|
{
|
|
97
113
|
test: /\.s[ac]ss$/,
|
|
98
|
-
use: ['
|
|
114
|
+
use: ['sass-loader'],
|
|
115
|
+
type: 'css/auto',
|
|
99
116
|
},
|
|
100
117
|
{
|
|
101
118
|
test: /\.(png|jpe?g|gif|svg)$/,
|
|
@@ -116,22 +133,27 @@ const config = async (env): Promise<Configuration> => {
|
|
|
116
133
|
|
|
117
134
|
optimization: {
|
|
118
135
|
minimize: Boolean(env.production),
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
136
|
+
splitChunks: {
|
|
137
|
+
cacheGroups: {
|
|
138
|
+
// CSS used by more than one lazy chunk goes into one shared file instead of a copy per chunk
|
|
139
|
+
sharedCss: {
|
|
140
|
+
type: /^css/,
|
|
141
|
+
chunks: 'async',
|
|
142
|
+
minChunks: 2,
|
|
143
|
+
minSize: 0,
|
|
144
|
+
priority: 10,
|
|
125
145
|
},
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
},
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
minimizer: [
|
|
149
|
+
new SwcJsMinimizerRspackPlugin({
|
|
150
|
+
extractComments: { banner: false },
|
|
151
|
+
minimizerOptions: {
|
|
152
|
+
format: { comments: false },
|
|
153
|
+
compress: { pure_funcs: ['console.log', 'console.info'] },
|
|
133
154
|
},
|
|
134
155
|
}),
|
|
156
|
+
new LightningCssMinimizerRspackPlugin(),
|
|
135
157
|
],
|
|
136
158
|
},
|
|
137
159
|
|
|
@@ -141,36 +163,45 @@ const config = async (env): Promise<Configuration> => {
|
|
|
141
163
|
},
|
|
142
164
|
filename: '[name].js',
|
|
143
165
|
chunkFilename: env.production ? '[name].js?_cache=[contenthash]' : '[name].js',
|
|
166
|
+
cssFilename: '[name].css',
|
|
167
|
+
cssChunkFilename: env.production ? '[name].css?_cache=[contenthash]' : '[name].css',
|
|
144
168
|
library: {
|
|
145
169
|
type: 'amd',
|
|
146
170
|
},
|
|
147
171
|
path: path.resolve(process.cwd(), DIST_DIR),
|
|
148
|
-
publicPath: `public/plugins/${
|
|
149
|
-
uniqueName:
|
|
172
|
+
publicPath: `public/plugins/${pluginId}/`,
|
|
173
|
+
uniqueName: pluginId,
|
|
150
174
|
crossOriginLoading: 'anonymous',
|
|
151
175
|
},
|
|
152
176
|
|
|
153
177
|
plugins: [
|
|
154
178
|
new BuildModeRspackPlugin(),
|
|
179
|
+
new LicenseRspackPlugin(),
|
|
180
|
+
new PluginCssRspackPlugin({ pluginId, publicPath: `public/plugins/${pluginId}/` }),
|
|
155
181
|
virtualPublicPath,
|
|
156
182
|
// Insert create plugin version information into the bundle
|
|
157
|
-
new
|
|
158
|
-
banner:
|
|
183
|
+
new BannerPlugin({
|
|
184
|
+
banner: [
|
|
185
|
+
`/* [create-plugin] version: ${cpVersion} */`,
|
|
186
|
+
`/* [create-plugin] plugin: ${pluginId}@${pluginVersion} */`,
|
|
187
|
+
].join('\n'),
|
|
159
188
|
raw: true,
|
|
160
189
|
entryOnly: true,
|
|
190
|
+
test: /\.js$/,
|
|
191
|
+
// after minification to prevent banner removal and before source maps and hashes are generated so they include it.
|
|
192
|
+
stage: Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE + 1,
|
|
161
193
|
}),
|
|
162
|
-
new
|
|
194
|
+
new CopyRspackPlugin({
|
|
163
195
|
patterns: copyFilePatterns,
|
|
164
196
|
}),
|
|
165
|
-
// Replace certain template-variables in the README and plugin.json
|
|
166
197
|
new ReplaceInFileWebpackPlugin([
|
|
167
198
|
{
|
|
168
199
|
dir: DIST_DIR,
|
|
169
|
-
|
|
200
|
+
test: [/(^|\/)plugin\.json$/, /(^|\/)README\.md$/],
|
|
170
201
|
rules: [
|
|
171
202
|
{
|
|
172
203
|
search: /\%VERSION\%/g,
|
|
173
|
-
replace:
|
|
204
|
+
replace: pluginVersion,
|
|
174
205
|
},
|
|
175
206
|
{
|
|
176
207
|
search: /\%TODAY\%/g,
|
|
@@ -178,7 +209,7 @@ const config = async (env): Promise<Configuration> => {
|
|
|
178
209
|
},
|
|
179
210
|
{
|
|
180
211
|
search: /\%PLUGIN_ID\%/g,
|
|
181
|
-
replace:
|
|
212
|
+
replace: pluginId,
|
|
182
213
|
},
|
|
183
214
|
],
|
|
184
215
|
},
|
|
@@ -196,9 +227,9 @@ const config = async (env): Promise<Configuration> => {
|
|
|
196
227
|
},
|
|
197
228
|
typescript: { configFile: path.join(process.cwd(), 'tsconfig.json') },
|
|
198
229
|
}),
|
|
199
|
-
new
|
|
200
|
-
|
|
201
|
-
|
|
230
|
+
new DiagnosticsRspackPlugin({
|
|
231
|
+
lintOnStart: false, // don't lint on start, only lint changed files
|
|
232
|
+
checks: [{ use: 'eslint', extensions: ['ts', 'tsx'] }],
|
|
202
233
|
}),
|
|
203
234
|
]
|
|
204
235
|
: []),
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"@grafana/plugin-e2e": "^3.15.2",
|
|
21
21
|
"@grafana/sign-plugin": "^3.3.3",
|
|
22
22
|
"@grafana/tsconfig": "^2.2.0",
|
|
23
|
-
"@playwright/test": "^1.62.1",{{#if
|
|
24
|
-
"@rspack/core": "^
|
|
25
|
-
"@rspack/cli": "^
|
|
23
|
+
"@playwright/test": "^1.62.1",{{#if useRspack}}
|
|
24
|
+
"@rspack/core": "^2.2.0",
|
|
25
|
+
"@rspack/cli": "^2.2.0",{{/if}}
|
|
26
26
|
"@stylistic/eslint-plugin": "^5.10.0",
|
|
27
27
|
"@swc/core": "^1.15.0",
|
|
28
28
|
"@swc/helpers": "^0.5.0",
|
|
@@ -32,47 +32,47 @@
|
|
|
32
32
|
"@types/jest": "^30.0.0",
|
|
33
33
|
"@types/node": "^24.0.0",
|
|
34
34
|
"@types/react": "^19.0.0",
|
|
35
|
-
"@types/react-dom": "^19.0.0",{{#if
|
|
35
|
+
"@types/react-dom": "^19.0.0",{{#if useRspack}}
|
|
36
36
|
"@types/ws": "^8.18.1",{{/if}}
|
|
37
37
|
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
|
38
|
-
"@typescript-eslint/parser": "^8.38.0",{{#unless
|
|
39
|
-
"copy-webpack-plugin": "^14.0.0",
|
|
40
|
-
"css-loader": "^7.1.0",{{
|
|
41
|
-
"diagnostics-webpack-plugin": "^1.0.1",
|
|
38
|
+
"@typescript-eslint/parser": "^8.38.0",{{#unless useRspack}}
|
|
39
|
+
"copy-webpack-plugin": "^14.0.0",
|
|
40
|
+
"css-loader": "^7.1.0",{{/unless}}
|
|
41
|
+
"diagnostics-webpack-plugin": "^1.0.1",
|
|
42
42
|
"eslint": "^9.32.0",
|
|
43
43
|
"eslint-config-prettier": "^10.1.0",
|
|
44
44
|
"eslint-plugin-jsdoc": "^52.0.0",
|
|
45
45
|
"eslint-plugin-react": "^7.37.0",
|
|
46
|
-
"eslint-plugin-react-hooks": "^7.1.0",{{#
|
|
47
|
-
"eslint-webpack-plugin": "^5.0.0",{{/if}}{{#unless useExperimentalRspack}}
|
|
46
|
+
"eslint-plugin-react-hooks": "^7.1.0",{{#unless useRspack}}
|
|
48
47
|
"fork-ts-checker-webpack-plugin": "^9.1.0",{{/unless}}
|
|
49
|
-
"identity-obj-proxy": "^3.0.0",
|
|
50
|
-
"imports-loader": "^5.0.0",
|
|
48
|
+
"identity-obj-proxy": "^3.0.0",{{#unless useRspack}}
|
|
49
|
+
"imports-loader": "^5.0.0",{{/unless}}
|
|
51
50
|
"intersection-observer": "^0.12.2",
|
|
52
51
|
"jest": "^30.5.0",
|
|
53
52
|
"jest-canvas-mock": "^2.5.2",
|
|
54
53
|
"jest-environment-jsdom": "^30.5.0",
|
|
55
54
|
"prettier": "^3.6.0",
|
|
56
|
-
"replace-in-file-webpack-plugin": "^1.0.0",{{#if
|
|
55
|
+
"replace-in-file-webpack-plugin": "^1.0.0",{{#if useRspack}}
|
|
56
|
+
"rspack-merge": "^1.0.1",
|
|
57
57
|
"rspack-plugin-virtual-module": "^1.0.0",{{/if}}
|
|
58
58
|
"sass": "^1.89.0",
|
|
59
59
|
"sass-loader": "^16.0.0",
|
|
60
|
-
"semver": "^7.7.0",
|
|
61
|
-
"style-loader": "^4.0.0",
|
|
62
|
-
"swc-loader": "^0.2.0",
|
|
63
|
-
"terser-webpack-plugin": "^5.3.0",
|
|
64
|
-
"ts-node": "^10.9.0",{{#if
|
|
65
|
-
"ts-checker-rspack-plugin": "^1.
|
|
60
|
+
"semver": "^7.7.0",{{#unless useRspack}}
|
|
61
|
+
"style-loader": "^4.0.0",
|
|
62
|
+
"swc-loader": "^0.2.0",
|
|
63
|
+
"terser-webpack-plugin": "^5.3.0",{{/unless}}
|
|
64
|
+
"ts-node": "^10.9.0",{{#if useRspack}}
|
|
65
|
+
"ts-checker-rspack-plugin": "^1.7.0",{{/if}}
|
|
66
66
|
"typescript": "5.9.2",
|
|
67
|
-
"webpack": "^5.106.0"{{#unless
|
|
67
|
+
"webpack": "^5.106.0"{{#unless useRspack}},
|
|
68
68
|
"webpack-cli": "^6.0.0",
|
|
69
69
|
"webpack-livereload-plugin": "^3.0.2",
|
|
70
70
|
"webpack-subresource-integrity": "^5.1.0",
|
|
71
|
-
"webpack-virtual-modules": "^0.6.2"{{/unless}}{{#if
|
|
71
|
+
"webpack-virtual-modules": "^0.6.2"{{/unless}}{{#if useRspack}},
|
|
72
72
|
"ws": "^8.13.0"{{/if}}
|
|
73
73
|
},
|
|
74
74
|
"engines": {
|
|
75
|
-
"node": ">=22"
|
|
75
|
+
"node": ">=22.23"
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
78
|
"@emotion/css": "11.10.6",
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import { Compilation, type Compiler } from '@rspack/core';
|
|
3
|
-
import { WebSocketServer } from 'ws';
|
|
4
|
-
import { createServer } from 'http';
|
|
5
|
-
|
|
6
|
-
interface RspackLiveReloadPluginOptions {
|
|
7
|
-
port?: number;
|
|
8
|
-
delay?: number;
|
|
9
|
-
appendScriptTag?: boolean;
|
|
10
|
-
protocol?: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
class RspackLiveReloadPlugin {
|
|
14
|
-
options: RspackLiveReloadPluginOptions;
|
|
15
|
-
httpServer: ReturnType<typeof createServer> | null = null;
|
|
16
|
-
server: WebSocketServer | null = null;
|
|
17
|
-
constructor(options = {}) {
|
|
18
|
-
this.options = Object.assign(
|
|
19
|
-
{
|
|
20
|
-
port: 35729,
|
|
21
|
-
delay: 0,
|
|
22
|
-
appendScriptTag: true,
|
|
23
|
-
protocol: 'http',
|
|
24
|
-
},
|
|
25
|
-
options
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
apply(compiler: Compiler) {
|
|
30
|
-
const isRspack = compiler.rspack !== undefined;
|
|
31
|
-
if (!isRspack) {
|
|
32
|
-
throw new Error('This plugin is designed to work with Rspack.');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
compiler.hooks.afterEmit.tap('RspackLiveReloadPlugin', (compilation) => {
|
|
36
|
-
this._startServer();
|
|
37
|
-
this._notifyClient();
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
compiler.hooks.done.tap('RspackLiveReloadPlugin', (stats) => {
|
|
41
|
-
if (this.options.appendScriptTag) {
|
|
42
|
-
this._injectLiveReloadScript(stats.compilation);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
_startServer() {
|
|
48
|
-
if (this.server) {
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const port = this.options.port;
|
|
53
|
-
|
|
54
|
-
this.httpServer = createServer((req, res) => {
|
|
55
|
-
if (req.url === '/livereload.js') {
|
|
56
|
-
res.writeHead(200, { 'Content-Type': 'application/javascript' });
|
|
57
|
-
res.end(this._getLiveReloadScript());
|
|
58
|
-
} else {
|
|
59
|
-
res.writeHead(404);
|
|
60
|
-
res.end('Not Found');
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
this.server = new WebSocketServer({ server: this.httpServer });
|
|
65
|
-
this.httpServer.listen(port, () => {
|
|
66
|
-
console.log(`LiveReload server started on http://localhost:${port}`);
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
_notifyClient() {
|
|
71
|
-
if (!this.server) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
this.server.clients.forEach((client) => {
|
|
76
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
77
|
-
client.send(JSON.stringify({ action: 'reload' }));
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
_injectLiveReloadScript(compilation: Compilation) {
|
|
83
|
-
compilation.hooks.processAssets.tap(
|
|
84
|
-
{
|
|
85
|
-
name: 'RspackLiveReloadPlugin',
|
|
86
|
-
stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
|
|
87
|
-
},
|
|
88
|
-
(assets) => {
|
|
89
|
-
Object.keys(assets).forEach((filename) => {
|
|
90
|
-
if (path.extname(filename) === '.html') {
|
|
91
|
-
const assetSource = compilation.getAsset(filename)?.source;
|
|
92
|
-
if (!assetSource) {
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const updatedSource = assetSource
|
|
97
|
-
.source()
|
|
98
|
-
.toString()
|
|
99
|
-
.replace('</body>', `<script src="http://localhost:${this.options.port}/livereload.js"></script></body>`);
|
|
100
|
-
|
|
101
|
-
compilation.updateAsset(filename, {
|
|
102
|
-
source: () => updatedSource,
|
|
103
|
-
buffer: () => Buffer.from(updatedSource),
|
|
104
|
-
size: () => updatedSource.length,
|
|
105
|
-
map: () => null,
|
|
106
|
-
sourceAndMap: () => ({ source: updatedSource, map: null }),
|
|
107
|
-
updateHash: (hash) => {
|
|
108
|
-
hash.update(updatedSource);
|
|
109
|
-
},
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
_getLiveReloadScript() {
|
|
118
|
-
return `
|
|
119
|
-
(function() {
|
|
120
|
-
if (typeof WebSocket === 'undefined') return;
|
|
121
|
-
const ws = new WebSocket('${this.options.protocol}://localhost:${this.options.port}');
|
|
122
|
-
ws.onmessage = function(event) {
|
|
123
|
-
const data = JSON.parse(event.data);
|
|
124
|
-
if (data.action === 'reload') {
|
|
125
|
-
window.location.reload();
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
})();
|
|
129
|
-
`;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export default RspackLiveReloadPlugin;
|