preactjs / prefresh Goto Github PK
View Code? Open in Web Editor NEWHot Module Reloading for Preact
License: MIT License
Hot Module Reloading for Preact
License: MIT License
We only want to wrap Components
with the refresh-runtime
for this we'll have to check the exports
provided (be that default or named) with an assumption.
Component
Hi there,
having problems getting this to work with preact/compat
version using React.memo
HOC.
If i have a component like:
export const Component = React.memo(function Foo(){
return <h1>Yo</h1>;
});
I receive an error like cannot read displayName of undefined
.
This also happens with React.forwardRef
Setting Componet.displayName = 'Foo';
does not solve it.
Any ideas?
Many thanks
When we see a file that exports a component as well as a custom hook (both can be identified with the @prefresh/utils
exports) we could warn our user that this can lead to indeterministic behaviour.
These warnings will most likely drastically change with #130
Now when you would add a dependency the effect would rerun, when you'd remove one it won't. This does feel pretty correct to me, the problem being that if you update the implementation of the hook that it won't rerun, this is the part I'm unsure about.
What do people expect?
Add a small hello world example (counter app) for every integration.
Debounce the flushing of updates through saving for webpack and next since these builds can take a while.
Mirror this from the main Preact repository
When we update a custom hook
we leave a stale reference in the Functional Components
using this hook. We need to find a way to ensure we're calling forceUpdate()
with the updated hook on these vnodes.
Let's say we update useCustomState.js
to return a different callback, this is implemented in our App.js
file. module.hot will trigger for useCustomState
and we'll know this is connected to the App type and it's vnode, however if we'd just force the update of this vnode we'd be executing a function with the stale version of useCustomState
. We'd have to force webpack to reevaluate this constructor (or need a way to get the new version of this constructor).
Concrete example:
export const useCounter = () => {
const [count, setCount] = useState(0):
return [count, () => { setCount(count + 1) }];
}
const Counter = () => {
const [count, increment] = useCounter();
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
Changing the second argument to increment by 2 will successfully get accepted but the event-handler will still only increment by 1.
It should be possible to create a Next.js plugin that does the following:
defaultLoaders.babel
include react-refresh/babel
hasReactRefresh = false
@prefresh/webpack
into the babel pluginsError
catchError.js:8 Uncaught TypeError: Cannot read property '__e' of undefined
at catchError.js:8
Happens in catchError.js
import { options } from '/@modules/preact/dist/preact.module.js';
import {
CATCH_ERROR_OPTION,
COMPONENT_DIRTY,
VNODE_COMPONENT
} from '/@modules/@prefresh/core/src/constants.js';
const oldCatchError = options[CATCH_ERROR_OPTION]; // options is undefined here
options[CATCH_ERROR_OPTION] = (error, vnode) => {
if (vnode[VNODE_COMPONENT] && vnode[VNODE_COMPONENT][COMPONENT_DIRTY]) {
vnode[VNODE_COMPONENT][COMPONENT_DIRTY] = false;
}
if (oldCatchError) oldCatchError(error, vnode);
};
Somehow it seems that Preact is not imported correctly. ๐คท I have tried to find the reason, but so far without success. Vite has introduced a breaking change in beta-2 that the vite client path has changed from /vite/hmr to /vite/client. Maybe it is related.
Hi,
I created a new application with preact-cli with the template typescript (I also tried default). When I use preact watch --refresh I have this error:
Uncaught TypeError: Cannot read property 'sign' of undefined at bundle.js:1611 at setup (common.js?f66b:7) at Object.eval (browser.js?52b2:167) at Object.55../common (browser.js?52b2:179) at o (_prelude.js?917a:1) at eval (_prelude.js?917a:1) at Object.eval (url.js?2b44:7) at Object.52.debug (url.js?2b44:10) at o (_prelude.js?917a:1) at eval (_prelude.js?917a:1)
The refresh
on class components currently happens correctly apart from one scenario
class Landing extends Component {
constructor(props) {
super(props);
this.state = { i: 0 };
this.increment = this.increment.bind(this); // this will make it fail!
}
increment() {
this.setState({ i: (this as any).state.i + 1 });
}
}
In the default vite template for preact, created with
npx create-vite-app preact-hmr --template preact
, editing the default app.jsx works as expected and is reflected on the page instantly. Any new component created and used within app.jsx
doesn't cause anything to change in the page when that new component is changed itself.
Posted in Vite. But thought maybe it might be directly related to this instead.
vitejs/vite#388 (comment)
When we for instance have a scenario where we load a component asynchronously
const MyLayComponent = lazy(() => import('comp'))
const App = () => {
return (
<Suspense>
<MyLazyComponent />
</Suspense>
)
}
and that component throws an error the vnode will exist but we have to navigate up the tree to start the refresh higher up since the dom still has to get connected from the parent.
Climbing the tree won't work since due to the nature of hot reloading that parent should not have the new Child function reference meaning we'd have to resort to reload()
Find out why the custom-hook key isn't present in signatures https://github.com/JoviDeCroock/prefresh/pull/16/files/31f63bada4416266d72ffb369c748424c985728f#diff-d1c352d7f9f3a715b84c656a6704289a
> csgo@1.0.0 dev C:\localhost\csgo
> cross-env NODE_OPTIONS='--inspect' next
Debugger listening on ws://127.0.0.1:9229/09daed7d-7fde-432b-b57f-f9776fcecd38
For help, see: https://nodejs.org/en/docs/inspector
[ wait ] starting the development server ...
[ info ] waiting on http://localhost:3000 ...
[ ready ] compiled successfully - ready on http://localhost:3000
[ event ] build page: /next/dist/pages/_error
[ wait ] compiling ...
Error: No dependency factory available for this dependency type: MultiEntryDependency
at Compilation._addModuleChain (C:\localhost\csgo\node_modules\webpack\lib\Compilation.js:1057:10)
at Compilation.addEntry (C:\localhost\csgo\node_modules\webpack\lib\Compilation.js:1164:8)
at C:\localhost\csgo\node_modules\next\dist\server\on-demand-entry-handler.js:2:168
at new Promise (<anonymous>)
at addEntry (C:\localhost\csgo\node_modules\next\dist\server\on-demand-entry-handler.js:2:58)
at C:\localhost\csgo\node_modules\next\dist\server\on-demand-entry-handler.js:3:129
at async Promise.all (index 0)
(node:3676) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'addChunk' of null
at Object.connectChunkAndModule (C:\localhost\csgo\node_modules\webpack\lib\GraphHelpers.js:35:13)
at Compilation.seal (C:\localhost\csgo\node_modules\webpack\lib\Compilation.js:1308:17)
at C:\localhost\csgo\node_modules\webpack\lib\Compiler.js:675:18
at C:\localhost\csgo\node_modules\webpack\lib\Compilation.js:1261:4
at AsyncSeriesHook.eval [as callAsync] (eval at create (C:\localhost\csgo\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonym
ous>:13:1)
at AsyncSeriesHook.lazyCompileHook (C:\localhost\csgo\node_modules\tapable\lib\Hook.js:154:20)
at Compilation.finish (C:\localhost\csgo\node_modules\webpack\lib\Compilation.js:1253:28)
at C:\localhost\csgo\node_modules\webpack\lib\Compiler.js:672:17
at eval (eval at create (C:\localhost\csgo\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:11:1)
(node:3676) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async fu
nction without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled p
romise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (
rejection id: 2)
(node:3676) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not han
dled will terminate the Node.js process with a non-zero exit code.
[ event ] build page: /support
[ event ] build page: /support
Integrate with Parcel 2 (maybe 1 as well if possible)
Look into support for Webpack 5 currently we're only supporting v4. I think it's worth deferring this to a later time when this is out of beta (RC)
This is a react-refresh implementation for WP5
Migration guide
Similar to #137
Hi there,
Running into this error using the webpack integration with the react-refresh/babel
plugin
packages/webpack/src/utils/createTemplate.js
// Execute the module function
const prevRefreshReg = window.$RefreshReg$; // ERROR: Window is undefined
const prevRefreshSig = window.$RefreshSig$;
I have tried modifying the globalObject
in the webpack output
to use this
, but unfortunately still doesn't work and seems to break other things.
webpack.config below:
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OUTPUT_DIR = 'dist';
const PreactRefreshPlugin = require('@prefresh/webpack');
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const mainEntries = [path.resolve(__dirname, './src/engine/client/index.tsx')];
// Exports
module.exports = {
entry: {
editor: mainEntries,
av: path.resolve(__dirname, './src/engine/client/AV/AVIndex.tsx'),
login: path.resolve(__dirname, './src/engine/client/Login/index.tsx'),
},
devServer: {
disableHostCheck: true,
port: 9000,
hot: true,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
'Access-Control-Allow-Headers':
'X-Requested-With, content-type, Authorization',
},
proxy: {
'/api': 'http://localhost:1234/dimsum/api',
},
},
mode: 'development',
stats: 'errors-only',
target: 'web',
devtool: 'eval-source-map',
node: {
fs: 'empty',
},
output: {
path: path.join(__dirname, OUTPUT_DIR),
pathinfo: false,
// publicPath: '/',
publicPath: 'http://localhost:9000/',
filename: 'dimsum/static/[name].pkgd.js',
chunkFilename: 'dimsum/static/[name].pkgd.js',
jsonpFunction: 'dimsumCoreJsonpFunction',
},
resolve: {
extensions: ['.wasm', '.mjs', '.js', '.jsx', '.ts', '.tsx', '.css'],
modules: [path.resolve(__dirname, 'node_modules')],
alias: {
// 'react-dom': '@hot-loader/react-dom',
react: 'preact/compat',
'react-dom/test-utils': 'preact/test-utils',
'react-dom': 'preact/compat',
},
},
optimization: {
splitChunks: {
// chunks: 'all',
cacheGroups: {
vendor: {
chunks: 'initial',
name: 'vendor',
enforce: true,
test: /node_modules/,
},
},
},
},
// optimization: {
// // removeAvailableModules: false,
// // removeEmptyChunks: false,
// splitChunks: false,
// },
module: {
rules: [
{
test: /\.worker\.ts$/,
use: [
{
loader: 'worker-loader',
options: { inline: true },
},
{
loader: 'babel-loader',
options: {
babelrc: false,
cacheDirectory: true,
presets: [
[
'@babel/env',
{
modules: false,
targets: {
browsers: ['last 2 versions'],
},
},
],
'@babel/typescript',
'@babel/react',
],
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-optional-chaining',
'react-refresh/babel',
],
},
},
],
},
{
test: /\.(ts|tsx)$/,
use: [
{
loader: 'babel-loader',
options: {
babelrc: false,
cacheDirectory: true,
presets: [
[
'@babel/env',
{
modules: false,
targets: {
browsers: ['last 2 versions'],
},
},
],
'@babel/typescript',
'@babel/react',
],
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-optional-chaining',
'transform-mui-imports',
'babel-plugin-styled-components',
'react-refresh/babel',
],
},
},
],
},
{
test: /\.css$/,
include: /node_modules/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(ttf|otf|woff|woff2)$/,
loader: 'file-loader',
},
],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new PreactRefreshPlugin(),
new MonacoWebpackPlugin({
languages: ['json', 'html', 'scss'],
}),
new MiniCssExtractPlugin({
filename: 'vendor.css',
chunkFilename: '[id].css',
}),
],
};
Replacing the declaration w
with the comment in the next line doesn't reset the state.
export function App() {
const [v] = useState(Math.random());
const [w] = useState(Math.random());
// const [w] = useState(Math.random() + 1);
return (
<div>
App <br />
{v} <br /> {w}
</div>
);
}
This might seem fine but if the datatype of the state changes and the value is used accordingly, you might get an invalid UI state.
(React Fast Refresh invalidates App
's state in this case and also when renaming the variable name w
to something else for the same reason.)
Strict package managers like pnpm and yarn 2 don't flatten the dependency tree meaning that if we inject @prefresh/core
or @prefresh/utils
into the client-codebase this won't resolve correctly due to it being a dependency
installed on the integration level rather than the base.
To circumvent this we'll need a few PR's like #80 to fix this issue. This puts these two dependencies at the root so it can be used from the installed module.
We should be able to hold on to hookState by having a set of heuristics to determine how we handle inserted/removed states, ...
// Reset hooks state
// TODO:
// allow resubbing context: https://github.com/preactjs/preact/pull/2501
// find reliable way of diffing depedency arrays
// find reliable way to assert inserted state hooks
// if (hooks && hooks.__) {
// const count = countStatefulHooks(hooks.__);
// Component.prototype.forceUpdate.call(c);
// const newCount = countStatefulHooks(hooks.__);
// if (count !== newCount) {
// // We'll have to reset hookState and call forceUpdate again.
// // There's another case where we add a dependency to a hook but
// // I'm not sure if we need to cover this.
// }
// } else {
// Component.prototype.forceUpdate.call(c);
// }
We should be able to recover from runtime errors, this seems to be correctly handled in prefresh
but the rerenderCount
in Preact isn't correctly reset making renders not occur.
Vite is now partially supported, this mainly works well for class components
and hooks
will have some quirks due to the missing babel plugin.
Releasing under @prefresh/vite
UPDATE: will make a PR one of these days where we run a small babel step.
I came across an issue where the state is not being persisted when using components defined in the same file. It compiles and runs, but once prefresh and nollup injects new code for it, the hook state is reset to 0. Preact example provided here
Another related issue is when using hooks like useMemo
inside components like here.
It exhibits Uncaught TypeError: undefined is not a function
or Uncaught (in promise) TypeError: $RefreshSig$ is not a function
when HMR injects this code.
I did verify that this works properly with the react-refresh example, so I guess these are related to the @prefresh/nollup plugin. Maybe this is @PepsRyuu's domain? :)
Define export maps in all packages
It's a lot of effort to publish at this moment, publish
, add Release to GH, ... I'd love to make this a little easier, I don't mind manually publishing to enable 2FA security but some easing up would be awesome.
Mention the measures we're taking to support strict-package managers as well as a high-level introduction how all of this works.
Webpack doesn't bundle after upgrading:
@prefresh/webpack
from 0.8.2
to 0.9.0
CLI error:
building ./node_modules/html-webpack-plugin/lib/child-compiler.js:175
return childCompilation.assets[helperFileName].source();
^
TypeError: Cannot read property 'source' of undefined
at ./node_modules/html-webpack-plugin/lib/child-compiler.js:175:52
at Array.map (<anonymous>)
at extractHelperFilesFromCompilation (./node_modules/html-webpack-plugin/lib/child-compiler.js:174:43)
at ./node_modules/html-webpack-plugin/lib/child-compiler.js:113:13
at ./node_modules/webpack/lib/Compiler.js:343:11
at ./node_modules/webpack/lib/Compiler.js:681:15
at AsyncSeriesHook.eval [as callAsync] (eval at create (./node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:24:1)
at AsyncSeriesHook.lazyCompileHook (./node_modules/tapable/lib/Hook.js:154:20)
at ./node_modules/webpack/lib/Compiler.js:678:31
at AsyncSeriesHook.eval [as callAsync] (eval at create (./node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
at AsyncSeriesHook.lazyCompileHook (./node_modules/tapable/lib/Hook.js:154:20)
at ./node_modules/webpack/lib/Compilation.js:1423:35
at AsyncSeriesHook.eval [as callAsync] (eval at create (./node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
at AsyncSeriesHook.lazyCompileHook (./node_modules/tapable/lib/Hook.js:154:20)
at ./node_modules/webpack/lib/Compilation.js:1414:32
at AsyncSeriesHook.eval [as callAsync] (eval at create (./node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
Hi there,
After upgrading from @prefresh/[email protected]
to @prefresh/[email protected]
, the following lines are injected into the browser code, causing a reference error:
require('@prefresh/vite/runtime');
const { compareSignatures } = require('@prefresh/vite/utils');
This can be reproduced by running the following:
$ yarn create vite-app test --template preact && cd test
$ yarn && yarn upgrade --latest && yarn dev
Everything works fine when pinning the version to 0.8.1
. Thanks! ๐
Kind regards,
Hampus Kraft.
Hey team, first off, wonderful job on what you all have done so far ๐ฏ
Just wanted to understand if this will support reloading in config with preact/compat
aliases as well? (particularly in the webpack 4 case).
If yes, how would one set this up to work in that environment.
If no, is it a case of "it's out of scope" or "support will be added later".
Thanks in advance :)
Currently we rely on detection because a Component
is exported, this doesn't feel quite right to me. A better alternative would be to use the register
function better.
This would allow us to detect non-exported Components within the same file, .... What we would have to do is only use module.hot
to schedule a reload
and then detect which components have changed with the register
function.
A register
means we will tie a function (Component) to an identifier
(moduleId), this allows us to do lookups. So if we change ComponentX we can't look this up by type anymore but the identifier
will have remained the same. When we see a register
for a function with an id that already exists we can safely assume this is a hot-reloaded component for which we should schedule a hot-reload.
Ideally this should be done by depth
but that doesn't feel 100% reliable at the moment.
Currently @prefresh/vite
injects code that directly imports from @prefresh/core
and @prefresh/utils
, which are not direct dependencies of the project, and cause the resolution to fail when using strict package managers like pnpm or yarn 2.
To make it compatible, we should use paths only under @prefresh/vite
.
I have a simple question: when vite comes with hot module reload itself, what's the differences between them? thanks for anybody's help. @yyx990803
I just released Vite 1.0.0-beta.1 which includes a number of breaking changes. Specifically, the transform API has changed and now also supports returning source map via return { code, map }
.
Let me know when you have a compatible release and I will update the template in create-vite-app
. Thanks!
Just wanted to leave a friendly heads up, attempted to upgrade today for better build times and got this error:
โฏ yarn dev
yarn run v1.22.4
warning package.json: No license field
$ next
ready - started server on http://localhost:3000
(node:23923) [DEP_WEBPACK_CONFIGURATION_OPTIMIZATION_NO_EMIT_ON_ERRORS] DeprecationWarning: optimization.noEmitOnErrors is deprecated in favor of optimization.emitOnErrors
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:23923) [DEP_WEBPACK_MAIN_TEMPLATE_REQUIRE] DeprecationWarning: MainTemplate.hooks.require is deprecated (use JavascriptModulesPlugin.getCompilationHooks().renderRequire instead)
(node:23923) [DEP_WEBPACK_EXTERNALS_FUNCTION_PARAMETERS] DeprecationWarning: The externals-function should be defined like ({context, request}, cb) => { ... }
/home/user/Projects/hasura-admin-next-preact/node_modules/webpack/lib/NormalModuleFactory.js:249
throw new Error(deprecationChangedHookMessage("afterResolve"));
^
Error: NormalModuleFactory.afterResolve is no longer a waterfall hook, but a bailing hook instead. Do not return the passed object, but modify it instead. Returning false will ignore the request and results in no module created.
Running with node --trace-deprecation ./node_modules/next/dist/bin/next
gives better error, and points to the exact bit of code:
โฏ node --trace-deprecation ./node_modules/next/dist/bin/next
ready - started server on http://localhost:3000
(node:27700) [DEP_WEBPACK_CONFIGURATION_OPTIMIZATION_NO_EMIT_ON_ERRORS] DeprecationWarning: optimization.noEmitOnErrors is deprecated in favor of optimization.emitOnErrors
at /home/user/Projects/hasura-admin-next-preact/node_modules/webpack/lib/config/normalization.js:201:9
at nestedConfig (/home/user/Projects/hasura-admin-next-preact/node_modules/webpack/lib/config/normalization.js:42:52)
at getNormalizedWebpackOptions (/home/user/Projects/hasura-admin-next-preact/node_modules/webpack/lib/config/normalization.js:180:17)
at createCompiler (/home/user/Projects/hasura-admin-next-preact/node_modules/webpack/lib/webpack.js:58:18)
at /home/user/Projects/hasura-admin-next-preact/node_modules/webpack/lib/webpack.js:40:48
at Array.map (<anonymous>)
at createMultiCompiler (/home/user/Projects/hasura-admin-next-preact/node_modules/webpack/lib/webpack.js:40:33)
at webpack (/home/user/Projects/hasura-admin-next-preact/node_modules/webpack/lib/webpack.js:108:14)
at f (/home/user/Projects/hasura-admin-next-preact/node_modules/webpack/lib/index.js:31:15)
at HotReloader.start (/home/user/Projects/hasura-admin-next-preact/node_modules/next/dist/server/hot-reloader.js:16:415)
(node:27700) [DEP_WEBPACK_MAIN_TEMPLATE_REQUIRE] DeprecationWarning: MainTemplate.hooks.require is deprecated (use JavascriptModulesPlugin.getCompilationHooks().renderRequire instead)
at /home/user/Projects/hasura-admin-next-preact/node_modules/@prefresh/next/src/plugin.js:46:43
Seems like this is the bit it's complaining about being deprecated (@prefresh/next/src/plugin.js:46:43
):
compiler.hooks.compilation.tap(NAME, compilation => {
compilation.mainTemplate.hooks.require.tap(NAME, (source, chunk, hash) =>
createRefreshTemplate(source, chunk, hash, compilation.mainTemplate)
);
});
DeprecationWarning: MainTemplate.hooks.require is deprecated (use JavascriptModulesPlugin.getCompilationHooks().renderRequire instead)
at /home/user/Projects/hasura-admin-next-preact/node_modules/@prefresh/next/src/plugin.js:46:43
At this point our hooks support is very basic, however we'd like to accurately handle:
effect
function signaturesWhen preact-cli
create new project, it will install @prefresh/webpack/example
's node_modules
. example
folder will occupy 38MB.
I think example
folder is unnecessary when we use @prefresh/webpack
, right ?
so I think it will reduce amount of file size if exclude example
folder when npm publish
(for now, new preact project's node_modules is 270MB ๐)
npx preact-cli@latest create default preact-project
and check @prefresh/webpack
file size
My suggestion is use npmignore
and gitignore
, but I don't know what the purpose of package.json's exports field
for and this package's publish flow.
So I think it's still need rely on you to consider again how to improve it.
Use changeset
or some other tool for automated changelogging
Currently next seems to always reset hookState this could be due to missing react-refresh/babel
, example app: developit/nextjs-preact-demo#16
It seems like Next.js handles modules differently and is using a different type of webpack injection. That's why our template is never injected doing the registration. We only have the hot handlers which will work fine but think that functional components always need full resets rather than statefull/stateless resets.
Next injection vs prefresh webpack injection
It seems like when in Next.js
every filename
is a function that returns an array of functions rather than an actual filename, the check for them whether or not to bind is not the filename extension but whether or not the module call is present.
The lines don't start with a module call but include it.
We'll probably need to write a custom plugin to properly support Next.
After fixing this I noticed there's another issue present when combined with preact-devtools
the hookState is kept around. These seem to be reset here
We need puppeteer tests for
We need tests for refreshing:
There seems to be some issue using hooks in components when using ts-loader
in combination with babel-loader
+ @babel/preset-env
and @prefresh/webpack
. For some reason, components with hooks become undefined
.
I have created a reproduction here. If you run the start
npm script, you will see the issue I'm talking about in your browser.
If you comment out these lines (remove @babel/preset-env
), the problem goes away.
If you return those lines and comment out these lines (remove ts-loader
), then everything works. But they can't seem to coexist.
Perhaps I have it misconfigured in some way. Is there something in @babel/preset-env
that would cause this? I would very much prefer to use ts-loader
together with babel-loader
, because there are also transformations that I want Typescript to make. However, in development I am using @prefresh/webpack
, so it refuses to work correctly.
One thing that is different between my main project repo and this reproduction: in my project repo, the element becomes <undefined>
, and doesn't throw the error in the browser. There is a lot more going on there, though, so there's apparently something that is allowing it to pass through as undefined
. I just didn't bother taking the time to build it up to that point. I just wanted to showcase the failure.
We'll need a build process so we can export both ESM
and CJS
, we should also use this oppurtunity to add export maps.
We could keep using cjyes
or we could try out microbundle
.
CC @developit any opinions?
As rightfully pointed out in #18 we're assigning some var
in the global scope, this makes it so that we could create intersections with things the user is defining. For that reason we should limit the amount of variable assignments to a minimum and give the ones we have left a prefixed name.
Snowpack 2 will be fleshing out their HMR support soon, let's participate in the RFC and make this work well for both react-refresh
and prefresh
.
Use $refreshReg$
to reload components that aren't exported, now we look at the moduleExports
Investigate what's wrong with @prefresh/next
and Node v14 developit/nextjs-preact-demo#16 (comment)
We can remove a lot of the module.hot.accept
code now that we have a flushing mechanic which simplifies the bundler integrations a lot.
We need to figure out how to integrate with Next.js and PR it to this repository it would be a huge plus if we could do this in a plugin.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.