refactor: react fast refresh
This commit is contained in:
parent
c3cc989aa5
commit
9404d73c00
8
lerna.json
Normal file
8
lerna.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"packages": [
|
||||||
|
"packages/*"
|
||||||
|
],
|
||||||
|
"useNx": true,
|
||||||
|
"version": "2.0.3"
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@flecks/monorepo",
|
"name": "@flecks/monorepo",
|
||||||
|
"private": true,
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/cha0s/flecks.git"
|
"url": "https://github.com/cha0s/flecks.git"
|
||||||
|
@ -26,10 +27,10 @@
|
||||||
"@flecks/server": "*",
|
"@flecks/server": "*",
|
||||||
"@flecks/socket": "*",
|
"@flecks/socket": "*",
|
||||||
"@flecks/user": "*",
|
"@flecks/user": "*",
|
||||||
"@flecks/web": "*",
|
"@flecks/web": "*"
|
||||||
"nx": "^17.2.8"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/theme-mermaid": "3.0.1"
|
"@docusaurus/theme-mermaid": "3.0.1",
|
||||||
|
"lerna": "^8.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,7 @@ export default (program, flecks) => {
|
||||||
cmd,
|
cmd,
|
||||||
{
|
{
|
||||||
env: {
|
env: {
|
||||||
|
FLECKS_CORE_IS_PRODUCTION: production,
|
||||||
...(target ? {FLECKS_CORE_BUILD_LIST: target} : {}),
|
...(target ? {FLECKS_CORE_BUILD_LIST: target} : {}),
|
||||||
...(hot ? {FLECKS_ENV__flecks_server__hot: 'true'} : {}),
|
...(hot ? {FLECKS_ENV__flecks_server__hot: 'true'} : {}),
|
||||||
},
|
},
|
||||||
|
|
|
@ -331,7 +331,7 @@ export default class ServerFlecks extends Flecks {
|
||||||
ignore: [ignore],
|
ignore: [ignore],
|
||||||
only: [only],
|
only: [only],
|
||||||
};
|
};
|
||||||
debugSilly('compiling %O with %j', compiling, config);
|
debugSilly('compiling %O with %j at %s', compiling, config, only);
|
||||||
compilations.push({
|
compilations.push({
|
||||||
ignore,
|
ignore,
|
||||||
only,
|
only,
|
||||||
|
@ -395,7 +395,8 @@ export default class ServerFlecks extends Flecks {
|
||||||
const roots = Array.from(new Set(
|
const roots = Array.from(new Set(
|
||||||
Object.keys(resolver)
|
Object.keys(resolver)
|
||||||
.map((path) => this.root(resolver, path))
|
.map((path) => this.root(resolver, path))
|
||||||
.filter((e) => !!e),
|
.filter((e) => !!e)
|
||||||
|
.concat(FLECKS_CORE_ROOT),
|
||||||
));
|
));
|
||||||
for (let i = 0; i < roots.length; ++i) {
|
for (let i = 0; i < roots.length; ++i) {
|
||||||
const root = roots[i];
|
const root = roots[i];
|
||||||
|
|
|
@ -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 = {
|
module.exports = {
|
||||||
aliases: {
|
|
||||||
'react-dom': '@hot-loader/react-dom',
|
|
||||||
},
|
|
||||||
babel: {
|
babel: {
|
||||||
|
plugins,
|
||||||
presets: [
|
presets: [
|
||||||
'@babel/preset-react',
|
'@babel/preset-react',
|
||||||
],
|
],
|
||||||
|
|
|
@ -44,13 +44,14 @@
|
||||||
"@babel/preset-react": "^7.23.3",
|
"@babel/preset-react": "^7.23.3",
|
||||||
"@flecks/core": "^2.0.3",
|
"@flecks/core": "^2.0.3",
|
||||||
"@flecks/web": "^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",
|
"babel-merge": "^3.0.0",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"history": "^5.3.0",
|
"history": "^5.3.0",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"react": "^18.2.0",
|
"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",
|
"react-router-dom": "6.20.0",
|
||||||
"redux-first-history": "5.1.1"
|
"redux-first-history": "5.1.1"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {D} from '@flecks/core';
|
import {D} from '@flecks/core';
|
||||||
import {hydrate, render} from '@hot-loader/react-dom';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import {createRoot, hydrateRoot} from 'react-dom/client';
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
import FlecksContext from '@flecks/react/context';
|
import FlecksContext from '@flecks/react/context';
|
||||||
|
@ -14,15 +14,19 @@ export const hooks = {
|
||||||
'@flecks/web/client.up': async (flecks) => {
|
'@flecks/web/client.up': async (flecks) => {
|
||||||
const {ssr} = flecks.get('@flecks/react');
|
const {ssr} = flecks.get('@flecks/react');
|
||||||
const {appMountId} = flecks.get('@flecks/web/client');
|
const {appMountId} = flecks.get('@flecks/web/client');
|
||||||
|
const container = window.document.getElementById(appMountId);
|
||||||
debug('%sing...', ssr ? 'hydrat' : 'render');
|
debug('%sing...', ssr ? 'hydrat' : 'render');
|
||||||
(ssr ? hydrate : render)(
|
const RootComponent = React.createElement(
|
||||||
React.createElement(
|
React.StrictMode,
|
||||||
React.StrictMode,
|
{},
|
||||||
{},
|
[React.createElement(await root(flecks), {key: 'root'})],
|
||||||
[React.createElement(await root(flecks), {key: 'root'})],
|
|
||||||
),
|
|
||||||
window.document.getElementById(appMountId),
|
|
||||||
);
|
);
|
||||||
|
if (ssr) {
|
||||||
|
hydrateRoot(container, RootComponent);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
createRoot(container).render(RootComponent);
|
||||||
|
}
|
||||||
debug('rendered');
|
debug('rendered');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
export {default as ReactDom} from '@hot-loader/react-dom';
|
|
||||||
export {default as classnames} from 'classnames';
|
export {default as classnames} from 'classnames';
|
||||||
export {default as PropTypes} from 'prop-types';
|
export {default as PropTypes} from 'prop-types';
|
||||||
export {default as React} from 'react';
|
export {default as React} from 'react';
|
||||||
|
export {default as ReactDom} from 'react-dom';
|
||||||
export * from 'react';
|
export * from 'react';
|
||||||
export {hot} from 'react-hot-loader';
|
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies, import/no-unresolved
|
// eslint-disable-next-line import/no-extraneous-dependencies, import/no-unresolved
|
||||||
export {default as FlecksContext} from '@flecks/react/context';
|
export {default as FlecksContext} from '@flecks/react/context';
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
import {Flecks} from '@flecks/core';
|
import {Flecks} from '@flecks/core';
|
||||||
import {augmentBuild} from '@flecks/web/server';
|
import {augmentBuild} from '@flecks/web/server';
|
||||||
|
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
|
||||||
|
|
||||||
import ssr from './ssr';
|
import ssr from './ssr';
|
||||||
|
|
||||||
export const hooks = {
|
export const hooks = {
|
||||||
'@flecks/core.build': (target, config, env, argv, flecks) => {
|
'@flecks/core.build': (target, config, env, argv, flecks) => {
|
||||||
const isProduction = 'production' === argv.mode;
|
const isProduction = 'production' === argv.mode;
|
||||||
config.resolve.alias['react-native'] = 'react-native-web';
|
if (!isProduction) {
|
||||||
config.resolve.alias['react-hot-loader'] = isProduction
|
config.plugins.push(new ReactRefreshWebpackPlugin());
|
||||||
? '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']);
|
|
||||||
// Augment the build on behalf of a missing `@flecks/web`.
|
// Augment the build on behalf of a missing `@flecks/web`.
|
||||||
if (!flecks.fleck('@flecks/web/server')) {
|
if (!flecks.fleck('@flecks/web/server')) {
|
||||||
flecks.registerBuildConfig('postcss.config.js', {fleck: '@flecks/web/server'});
|
flecks.registerBuildConfig('postcss.config.js', {fleck: '@flecks/web/server'});
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {Transform} from 'stream';
|
||||||
|
|
||||||
import {D} from '@flecks/core';
|
import {D} from '@flecks/core';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOMServer from '@hot-loader/react-dom/server';
|
import ReactDOMServer from 'react-dom/server';
|
||||||
|
|
||||||
import root from './root';
|
import root from './root';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
aliases: {
|
|
||||||
'react-dom': '@hot-loader/react-dom',
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -29,7 +29,6 @@
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@flecks/core": "^2.0.3",
|
"@flecks/core": "^2.0.3",
|
||||||
"@hot-loader/react-dom": "^17.0.1",
|
|
||||||
"@reduxjs/toolkit": "^1.5.0",
|
"@reduxjs/toolkit": "^1.5.0",
|
||||||
"debug": "^4.3.3",
|
"debug": "^4.3.3",
|
||||||
"lodash.throttle": "^4.1.1",
|
"lodash.throttle": "^4.1.1",
|
||||||
|
|
|
@ -86,33 +86,8 @@ Now if you visit the page with JavaScript disabled, you will get a white page.
|
||||||
|
|
||||||
### Hot module reloading
|
### Hot module reloading
|
||||||
|
|
||||||
This is cool, but you'll notice that if you edit your component, the changes are not immediately
|
You'll notice that if you edit your component, the changes are immediately reflected on the page.
|
||||||
reflected on the page. This is because we have to add HMR support to our root component:
|
This is because we have HMR support in our application!
|
||||||
|
|
||||||
```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)!
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Hooks
|
## Hooks
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user