Skip to content

Commit

Permalink
feat(devtools): refactor mounting logic and inject options to client (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Asuka109 authored Jan 24, 2024
1 parent 0b92053 commit b7109a7
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 88 deletions.
6 changes: 6 additions & 0 deletions .changeset/wicked-bikes-breathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@modern-js/devtools-client': patch
'@modern-js/plugin-devtools': patch
---

refactor(devtools): mounting logic and inject options to client
13 changes: 0 additions & 13 deletions packages/devtools/client/exports/.eslintrc.js

This file was deleted.

40 changes: 0 additions & 40 deletions packages/devtools/client/exports/mount.mjs

This file was deleted.

1 change: 1 addition & 0 deletions packages/devtools/client/modern.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export default defineConfig<'rspack'>({
'process.env.VERSION': packageMeta.version,
'process.env.PKG_VERSION': packageMeta.version,
'process.env.DEVTOOLS_MARK': nanoid(),
__REACT_DEVTOOLS_GLOBAL_HOOK__: { isDisabled: true },
},
alias: {
// Trick to fix: Modern.js won't recognize experimental react as react@18.
Expand Down
2 changes: 1 addition & 1 deletion packages/devtools/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"main": "./dist/html/client/index.html",
"exports": {
".": "./dist/html/client/index.html",
"./mount": "./exports/mount.mjs",
"./manifest": "./dist/routes-manifest.json",
"./sw-proxy": "./dist/public/sw-proxy.js",
"./package.json": "./package.json"
},
Expand Down
53 changes: 29 additions & 24 deletions packages/devtools/client/src/entries/mount/index.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
import './react-devtools-backend';
import './state';
import { createRoot } from 'react-dom/client';
import { parseQuery } from 'ufo';
import _ from 'lodash';
import { SetupClientParams } from '@modern-js/devtools-kit';
import styles from './index.module.scss';
import { DevtoolsActionButton } from '@/components/Devtools/Action';

// @ts-expect-error
const { container, resourceQuery } = window._modern_js_devtools_app as {
container: HTMLDivElement;
resourceQuery: string;
};
container.classList.add(styles.container);
const root = createRoot(container);
const parsed = parseQuery(resourceQuery);
if (
!_.isString(parsed.dataSource) ||
!_.isString(parsed.def) ||
!_.isString(parsed.endpoint)
) {
throw new TypeError(
`Failed to parse client definitions of devtools: ${resourceQuery}`,
);
declare global {
interface Window {
__MODERN_JS_DEVTOOLS_OPTIONS__: SetupClientParams;
}
}
const options: SetupClientParams = {
dataSource: parsed.dataSource,
endpoint: parsed.endpoint,
def: JSON.parse(parsed.def),
};

root.render(<DevtoolsActionButton {...options} />);
document.addEventListener('DOMContentLoaded', () => {
const outer = document.createElement('div');
outer.className = '_modern_js_devtools_container';
document.body.appendChild(outer);

const shadow = outer.attachShadow({ mode: 'closed' });

const template = document.getElementById('_modern_js_devtools_styles');
if (!(template instanceof HTMLTemplateElement)) {
throw new Error('template not found');
}
shadow.appendChild(template.content);

const container = document.createElement('div');
container.classList.add(
'_modern_js_devtools_mountpoint',
'theme-register',
styles.container,
);
shadow.appendChild(container);

const options = window.__MODERN_JS_DEVTOOLS_OPTIONS__;
const root = createRoot(container);
root.render(<DevtoolsActionButton {...options} />);
});
51 changes: 41 additions & 10 deletions packages/devtools/plugin/src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import http from 'http';
import path from 'path';
import assert from 'assert';
import { ProxyDetail } from '@modern-js/types';
import { getPort, logger } from '@modern-js/utils';
import createServeMiddleware from 'serve-static';
import type { AppTools, CliPlugin } from '@modern-js/app-tools';
import { ROUTE_BASENAME } from '@modern-js/devtools-kit';
import { withQuery } from 'ufo';
import {
DevtoolsPluginOptions,
DevtoolsPluginInlineOptions,
Expand Down Expand Up @@ -58,24 +58,55 @@ export const devtoolsPlugin = (
});
logger.info(`${ctx.def.name.formalName} Devtools is enabled`);

const runtimeEntry = require.resolve(
'@modern-js/devtools-client/mount',
);

const swProxyEntry = require.resolve(
'@modern-js/devtools-client/sw-proxy',
);

// Inject options to client.
const serializedOptions = JSON.stringify(ctx);
const tags: AppTools['normalizedConfig']['html']['tags'] = [
{
tag: 'script',
children: `window.__MODERN_JS_DEVTOOLS_OPTIONS__ = ${serializedOptions};`,
head: true,
append: false,
},
];

const styles: string[] = [];
const manifest = require('@modern-js/devtools-client/manifest');
// Inject JavaScript chunks to client.
for (const src of manifest.routeAssets.mount.assets) {
assert(typeof src === 'string');
if (src.endsWith('.js')) {
tags.push({
tag: 'script',
attrs: { src },
head: true,
append: false,
});
} else if (src.endsWith('.css')) {
styles.push(src);
}
}
// Inject CSS chunks to client inside of template to avoid polluting global.
tags.push({
tag: 'template',
attrs: { id: '_modern_js_devtools_styles' },
append: true,
head: false,
children: styles
.map(src => `<link rel="stylesheet" href="${src}">`)
.join(''),
});

return {
builderPlugins: [rpc.builderPlugin],
source: {
preEntry: [withQuery(runtimeEntry, ctx)],
include: [runtimeEntry],
},
source: {},
output: {
copy: [{ from: swProxyEntry, to: 'public' }],
},
html: {},
html: { tags },
tools: {
devServer: {
proxy: {
Expand Down

0 comments on commit b7109a7

Please sign in to comment.