I am relatively new to react and webpack, and I just picked up a new project to work on. To configure DevTool, we have:
export function renderDevTools(store) {
if (__DEV__) {
let {DevTools, DebugPanel, LogMonitor} = require('redux-devtools/lib/react');
return (
<DebugPanel top right bottom>
<DevTools store={store} monitor={LogMonitor} />
</DebugPanel>
);
}
return null;
}
From the node_module, I can see:
\node_modules\redux-devtools\lib\
has
createDevTools.js
index.js
persistState.js
but there is no react.js in this folder, so running the code will give:
ERROR in ./app/utils/devTools.js
Module not found: Error: Cannot resolve module 'redux-devtools/lib/react'
I have tried
npm install redux-devtools
but there is still missing react from the file. This is a legacy code, and when I tried running it, it isn't working. I am wondering what went wrong?
This code is for redux-devtools#2. In redux-devtools#3 monitors are decoupled into redux-devtools-log-monitor and redux-devtools-dock-monitor, which you have also to install and add to you project as indicated in the docs.
Also you have to set __DEV__ as true in webpack.config (which should be different for development and production):
plugins: [
new webpack.DefinePlugin({
'__DEV__': true
})
],
A easier way is not to include it directly into your app, but to use Chrome / Firefox extension. Then you can add it to your Redux store with just one line of code:
const store = createStore(reducer, /* preloadedState, */
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
Make sure to remove everything else related to Redux DevTools in this case.
If you're using the extension you can use it also in production without any edge cases, otherwise make sure to remove it from production bundle.
Related
I'm trying to use node-jsencrypt with NextJS (tsx):
index.tsx
import JSEncrypt from 'node-jsencrypt';
package.json
"node-jsencrypt": "^1.0.0"
Log
error - ./node_modules/node-jsencrypt/index.js:2:0
Module not found: Can't resolve 'fs'
Notes:
I didn't find the 'webpack.config.js' file, as I saw in some topics.
Ok, I played around with this issue & I think I have what cover all possible combinations. In the repo you can find working examples. There are 3 possible approaches, and the right one will depend on what's already in your project - details that were unspecified in the original question.
Solution while using webpack 5 next.config.js
module.exports = {
future: {
webpack5: true, // by default, if you customize webpack config, they switch back to version 4.
// Looks like backward compatibility approach.
},
webpack(config) {
config.resolve.fallback = {
...config.resolve.fallback, // if you miss it, all the other options in fallback, specified
// by next.js will be dropped. Doesn't make much sense, but how it is
fs: false, // the solution
};
return config;
},
};
Solution while using webpack 4 - next.config.js
module.exports = {
webpack(config) { // we depend on nextjs switching to webpack 4 by default. Probably they will
// change this behavior at some future major version.
config.node = {
fs: "empty", // webpack4 era solution
};
return config;
},
};
You could consider using other library. According to node-jsencrypt readme they are node port of jsencrypt, and here I assume you try to build for browser. The node library got stuck at version 1, while the original library is already at version 3. As I checked in the last commit on main, if you use this library, it's building just fine without any issues.
Original, nextjs unaware answer:
Since version 5, webpack doesn't include polyfiles for node libraries. In your case, you most likely need to add resolve.fallback.fs: false to your webpack config.
More about this option- https://webpack.js.org/configuration/resolve/#resolvefallback
It mentioned in v4 to v6 migration guide, if this is your case:
https://webpack.js.org/migrate/5/
In the next.config.js file add the code below
build: {
extend(config, {}) {
config.node = {
fs: 'empty'
}
}
},
I'm using this tutorial to make a React app. I have the most updated webpack-CLI 4.2.0 in devDependencies. I looked in node_modules/webpack-cli/bin/config-yargs but its not there. It only goes as far as 'bin' and it has one file in it. It's also telling me about
`(/Users/danielengel/Desktop/Project portfolio/watches/node_modules/webpack-dev-server/bin/webpack-dev-server.js:65:1)`
It has
// webpack-cli#3.3 path : webpack-cli/bin/config/config-yargs
let configYargsPath;
try {
require.resolve('webpack-cli/bin/config/config-yargs');
configYargsPath = 'webpack-cli/bin/config/config-yargs';
} catch (e) {
configYargsPath = 'webpack-cli/bin/config-yargs';
}
// eslint-disable-next-line import/no-extraneous-dependencies
// eslint-disable-next-line import/no-dynamic-require
require(configYargsPath)(yargs);
, And at the top of the file it has
`const yargs = require('yargs');
I've tried commenting out some of the code, or uncommenting in the node_modules but I know that's a bad idea. I also tried uninstalling and reinstalling the webpacks with NPM. I tried changing it to a regular dependency instead of dev-dependency. I tried installing it globally too.
Try using webpack serves instead of webpack-dev-server in package.json
I created a rust-wasm module and use workerize-loader to load it:
export const getQRCode = async (
arg: string,
width: number,
height: number
) => {
const { qrcode } = await import('uranus-qrcode');
return qrcode(arg, width, height);
};
and then I use the worker as such:
// #ts-ignore
// eslint-disable-next-line import/no-webpack-loader-syntax
import qrCodeWorker from 'workerize-loader!workers/qrCodeWorker';
...
const workerizeQRLoader = async () => {
try {
const instance = qrCodeWorker();
const qr = await instance.getQRCode(href, 150, 150);
setQRCode({
__html: qr
});
} catch (e) {
console.warn(e);
}
};
...
useEffect(() => {
workerizeQRLoader();
// qrLoader();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
...
The above works in dev mode, but after compiling it says:
TypeError: a.getQRCode is not a function
at 8.a2ac9b2e.chunk.js:1
at l (0.69608c56.chunk.js:2)
at Generator._invoke (0.69608c56.chunk.js:2)
at Generator.forEach.e.<computed> [as next] (0.69608c56.chunk.js:2)
at r (0.69608c56.chunk.js:2)
at s (0.69608c56.chunk.js:2)
at 0.69608c56.chunk.js:2
at new Promise (<anonymous>)
at 0.69608c56.chunk.js:2
at 8.a2ac9b2e.chunk.js:1
If I import the rust-wasm module directly into the main thread it works:
...
const qrLoader = async () => {
const { qrcode: render } = await import('uranus-qrcode');
const qr = await render(href, 150, 150);
setQRCode({
__html: qr
});
};
useEffect(() => {
// workerizeQRLoader();
qrLoader();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
...
Basically I try to get React (Webpack & TypeScript flavor) to load WebAssembly modules (aka wasm, created via Rust-Wasmbindgen) through web workers. I've tried workerize-loader + wasm-loader, and it works pretty well in the dev mode but once it is compiled, the prototype will not be added to the worker (suspecting it's a bug in workerize-loader because all workerized modules behave the same). I also tried to work with worker-loader + comlink, but the worker-loader doesn't seem to work with wasm-loader (would not be able to import wasm into the worker). The only way to get this to work is to load wasm into the main thread via wasm-loader and just give up the multi-threads setup which is basically a shame...so does anyone have successfully use a WebAssembly module loaded through a web worker in a React TypeScript project? What's your setup?
I also created a starter project: https://github.com/aeroxy/react-typescript-webassembly-starter.git
You can checkout the "workerize" branch and see how it works in dev mode but after compiling, it throws "not a function" error.
This is a bit much for a comment but I got some bad and good news. Executed the following commands using node v12.16.1 and yarn 1.22.4:
git clone https://github.com/aeroxy/react-typescript-webassembly-starter.git
cd react-typescript-webassembly-starter
yarn # some warnings that packages need to be updated to later version
yarn start # dev version works
yarn build
cd build
npx serve
When opening the build version in Google Chrome 81.0.4044.113 (Official Build) (64-bit) on my Fedora 31 I can see the qr code, no errors in console.
That means that there is no fault in the project (good news) but something maybe wrong in settings on your machine (bad news), the os you are using or some other machine specific difference.
You could try a to clone the project again and run the commands exactly like I did to see if that's working. Older npm could have some problems with cached packages but that's been fixed for a while now. A while ago you needed to change the repository for npm or use vpn because it was blocked, this could also be causing you trouble.
This is a duplicate of my original answer but got deleted for some odd reason by a moderator without leaving a reason.
Now the workerize method works!
I've originally tried workerize-loader + wasm-loader, and it works pretty well in the dev mode but once it is compiled, the prototype will not be added to the worker (suspecting it's a bug in workerize-loader because all workerized modules behave the same). This indeed turns out to be a bug in workerize-loader (see workerize-loader failed to work after compiling and Version 1.2.0 does not export function on worker instance in production mode). After upgrading to the workerize-loader 1.2.1, it works in both dev and prod code.
I have updated the Master repo: https://github.com/aeroxy/react-typescript-webassembly-starter.git
I have a purchased react template with the following lines, but its not clear to me whats the purpose of this, the template its in JS and I want to change it to Typescript
The following lines were present in the template
if (module.hot) {
module.hot.accept('./dashApp.js', () => {
const NextApp = require('./dashApp').default;
ReactDOM.render(<NextApp />, document.getElementById('root'));
});
}
However when renamed to .TS, I get this error:
Property 'hot' does not exist on type 'NodeModule'.ts(2339)
What does this code really does? in plain english
This code is related to Webpack's hot module replacement feature (HMR). module.hot works like this:
module.hot.accept(
dependencies, // Either a string or an array of strings
callback // Function to fire when the dependencies are updated
);
So the code you included does this: *when the code of ./dashApp.js or one of the module it requires/imports in the requirement/import tree gets updated, re-render the whole React app.
The hot property on node modules it not standard, thus the TS error - make sure you install the required type definitions! npm install --save-dev #types/webpack-env should do the trick.
Related reads:
Hot Module Replacement concept: high-level Webpack doc on HMR
Hot Module Replacement API low-level Webpack doc on HMR, explaining how to use it and how does module.hot.accept does
Property 'hot' does not exist on type 'NodeModule': Github issue resolving the TS error
Just to add to the accepted answer: After installing #types/webpack-env you might have to add "types": ["webpack-env"] to your tsconfig.json in compilerOptions. Only then it finally worked for me.
So your tsconfig.json would look like this:
{
"compilerOptions": {
...
"types": ["webpack-env"]
},
...
}
I just started working with React last week, and I'm having trouble following a tutorial for the static-render-webpack-plugin.
I've put the code online at GitHub if you want to take a closer look.
After following the tutorial and making a couple of changes (I added babel-core, I changed the js loader to babel-loader and the entry point url needed a small correction), when I try to run webpack -p to generate the static files I get the following error:
ERROR in ./src/entry.js
Module build failed: SyntaxError: .../src/entry.js: Unexpected token (10:2)
8 |
9 | const routes = (
> 10 | <Route path="/" handler={RootPage}>
| ^
I think it might have something to do with the changes made with the latest version of react-router. I'm using the latest version, but the syntax for the tutorial looks like it might have been written prior to v.1.0. For example, I think the part of the tutorial that says to add this to the src/entry.js file:
if (typeof document != 'undefined') {
Router.run(routes, path, (Root) => {
React.render(<Root/>, document);
});
}
probably needs to be rewritten to something like this (but I'm not sure if this is quite right):
if (typeof document != 'undefined') {
ReactDOM.render(routes, document);
}
There's obviously more going on though since I get the same error message when I try that rewritten snippet then run webpack-dev-server -- which is the only time it should hit that code. (Yes, I added import ReactDOM from 'react-dom'; to the top of the page and "react-dom": "^0.14.7", to the package.json.)
I am sure this part (also on src/entry.js) needs to be rewritten to match the latest react-router too but I'm not sure how:
export default function(path, props, callback) {
Router.run(routes, path, (Root) => {
const html = React.renderToString(<Root/>);
callback('<!doctype html>' + html);
});
}
Thanks in advance for any help or hints you can give.
Your code is breaking because Webpack doesn't know how to transpile the JSX to ES5. You've specified babel-loader as your loader for JS files in your webpack config, but unfortunately Babel 6 does not do anything out of the box, you need to include "plugins" that contain the rules for compiling different syntaxes down to ES5. In this case, you'll want the es2015 preset to support all ES6 syntax, and the react preset to support JSX. You're also missing the extract-text-webpack-plugin you are trying to import into your webpack config. Snag these through NPM:
npm i -D babel-preset-2015 babel-preset-react extract-text-webpack-plugin
Then, add the presets to your webpack.config.js file in the loaders section for js/jsx files:
{
test: /\.(js|jsx)?$/,
loader: 'babel',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
}
I forked your repo and made these changes and was able to get a bit further through the compilation process. It seems like there are module dependencies specific to your project you'll still need to resolve.