refactor: react fast refresh

This commit is contained in:
cha0s 2024-01-10 04:36:02 -06:00
parent c3cc989aa5
commit 9404d73c00
13 changed files with 50 additions and 59 deletions

8
lerna.json Normal file
View File

@ -0,0 +1,8 @@
{
"packages": [
"packages/*"
],
"useNx": true,
"version": "2.0.3"
}

View File

@ -1,5 +1,6 @@
{
"name": "@flecks/monorepo",
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/cha0s/flecks.git"
@ -26,10 +27,10 @@
"@flecks/server": "*",
"@flecks/socket": "*",
"@flecks/user": "*",
"@flecks/web": "*",
"nx": "^17.2.8"
"@flecks/web": "*"
},
"dependencies": {
"@docusaurus/theme-mermaid": "3.0.1"
"@docusaurus/theme-mermaid": "3.0.1",
"lerna": "^8.0.2"
}
}

View File

@ -113,6 +113,7 @@ export default (program, flecks) => {
cmd,
{
env: {
FLECKS_CORE_IS_PRODUCTION: production,
...(target ? {FLECKS_CORE_BUILD_LIST: target} : {}),
...(hot ? {FLECKS_ENV__flecks_server__hot: 'true'} : {}),
},

View File

@ -331,7 +331,7 @@ export default class ServerFlecks extends Flecks {
ignore: [ignore],
only: [only],
};
debugSilly('compiling %O with %j', compiling, config);
debugSilly('compiling %O with %j at %s', compiling, config, only);
compilations.push({
ignore,
only,
@ -395,7 +395,8 @@ export default class ServerFlecks extends Flecks {
const roots = Array.from(new Set(
Object.keys(resolver)
.map((path) => this.root(resolver, path))
.filter((e) => !!e),
.filter((e) => !!e)
.concat(FLECKS_CORE_ROOT),
));
for (let i = 0; i < roots.length; ++i) {
const root = roots[i];

View File

@ -1,8 +1,16 @@
const plugins = [];
const {
FLECKS_CORE_IS_PRODUCTION,
} = process.env;
if ('true' !== FLECKS_CORE_IS_PRODUCTION) {
plugins.push('react-refresh/babel');
}
module.exports = {
aliases: {
'react-dom': '@hot-loader/react-dom',
},
babel: {
plugins,
presets: [
'@babel/preset-react',
],

View File

@ -44,13 +44,14 @@
"@babel/preset-react": "^7.23.3",
"@flecks/core": "^2.0.3",
"@flecks/web": "^2.0.3",
"@hot-loader/react-dom": "^17.0.2",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.11",
"babel-merge": "^3.0.0",
"classnames": "^2.3.1",
"history": "^5.3.0",
"prop-types": "^15.7.2",
"react": "^18.2.0",
"react-hot-loader": "^4.13.1",
"react-dom": "^18.2.0",
"react-refresh": "^0.14.0",
"react-router-dom": "6.20.0",
"redux-first-history": "5.1.1"
},

View File

@ -1,6 +1,6 @@
import {D} from '@flecks/core';
import {hydrate, render} from '@hot-loader/react-dom';
import React from 'react';
import {createRoot, hydrateRoot} from 'react-dom/client';
// eslint-disable-next-line import/no-extraneous-dependencies
import FlecksContext from '@flecks/react/context';
@ -14,15 +14,19 @@ export const hooks = {
'@flecks/web/client.up': async (flecks) => {
const {ssr} = flecks.get('@flecks/react');
const {appMountId} = flecks.get('@flecks/web/client');
const container = window.document.getElementById(appMountId);
debug('%sing...', ssr ? 'hydrat' : 'render');
(ssr ? hydrate : render)(
React.createElement(
const RootComponent = React.createElement(
React.StrictMode,
{},
[React.createElement(await root(flecks), {key: 'root'})],
),
window.document.getElementById(appMountId),
);
if (ssr) {
hydrateRoot(container, RootComponent);
}
else {
createRoot(container).render(RootComponent);
}
debug('rendered');
},
};

View File

@ -1,9 +1,8 @@
export {default as ReactDom} from '@hot-loader/react-dom';
export {default as classnames} from 'classnames';
export {default as PropTypes} from 'prop-types';
export {default as React} from 'react';
export {default as ReactDom} from 'react-dom';
export * from 'react';
export {hot} from 'react-hot-loader';
// eslint-disable-next-line import/no-extraneous-dependencies, import/no-unresolved
export {default as FlecksContext} from '@flecks/react/context';

View File

@ -1,16 +1,15 @@
import {Flecks} from '@flecks/core';
import {augmentBuild} from '@flecks/web/server';
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
import ssr from './ssr';
export const hooks = {
'@flecks/core.build': (target, config, env, argv, flecks) => {
const isProduction = 'production' === argv.mode;
config.resolve.alias['react-native'] = 'react-native-web';
config.resolve.alias['react-hot-loader'] = isProduction
? 'react-hot-loader/dist/react-hot-loader.production.min'
: 'react-hot-loader/dist/react-hot-loader.development';
config.resolve.extensions.unshift(...['.web.js', '.web.jsx']);
if (!isProduction) {
config.plugins.push(new ReactRefreshWebpackPlugin());
}
// Augment the build on behalf of a missing `@flecks/web`.
if (!flecks.fleck('@flecks/web/server')) {
flecks.registerBuildConfig('postcss.config.js', {fleck: '@flecks/web/server'});

View File

@ -2,7 +2,7 @@ import {Transform} from 'stream';
import {D} from '@flecks/core';
import React from 'react';
import ReactDOMServer from '@hot-loader/react-dom/server';
import ReactDOMServer from 'react-dom/server';
import root from './root';

View File

@ -1,5 +0,0 @@
module.exports = {
aliases: {
'react-dom': '@hot-loader/react-dom',
},
};

View File

@ -29,7 +29,6 @@
],
"dependencies": {
"@flecks/core": "^2.0.3",
"@hot-loader/react-dom": "^17.0.1",
"@reduxjs/toolkit": "^1.5.0",
"debug": "^4.3.3",
"lodash.throttle": "^4.1.1",

View File

@ -86,33 +86,8 @@ Now if you visit the page with JavaScript disabled, you will get a white page.
### Hot module reloading
This is cool, but you'll notice that if you edit your component, the changes are not immediately
reflected on the page. This is because we have to add HMR support to our root component:
```jsx title="packages/root/src/component.jsx"
import {hot, React} from '@flecks/react';
function Component() {
return <p>hello world (from React)</p>;
}
export default hot(module)(Component);
```
Now you can edit and your changes will be reflected on the page!
:::tip
Any components your root component uses will automatically be reloaded: only your root component
requires the `hot` call.
:::note[Help wanted]
It is admittedly not so ergonomic to remember the `hot` call for your root components. React fast
refresh would probably make this unnecessary, but it hasn't been implemented in flecks yet. We
would very much appreciate a [pull request](https://github.com/cha0s/flecks/compare)!
:::
You'll notice that if you edit your component, the changes are immediately reflected on the page.
This is because we have HMR support in our application!
## Hooks