How to use a CommonJS module in React with Webpack? - reactjs

I'm trying to install this React library:
html-2-jsx
Problem is, i don't know how to import it into React. The description says:
To use the Node.js module, require('htmltojsx') and create a new instance.
When i try to just require it in the React component, ESlint tells me:
File is a CommonJS module. It may be converted to an ES6 module.
Of course, when i try to run Webpack, i get errors.
The errors i get in Webpack:
Can't resolve 'child_process' in
'C:\xampp\htdocs\codeigniter_cms\public\node_modules\xmlhttprequest\lib'
And few errors of this kind:
Can't resolve 'fs' in
'C:\xampp\htdocs\codeigniter_cms\public\node_modules\cssstyle\lib'
How can this be done? To be honest, i find it a bit weird, that a library made for react, doesn't support ES6 import functionality.

Try adding this to your webpack config:
module.exports = {
...
node: {
fs: 'empty',
child_process: 'empty'
}
};
The warning you are seeing has nothing to do with those errors. If you'd like to fix the warning then it may require some context on where the warning occurs.

Related

Mocking TypeScript imports for Storybook

I am attempting to mock the import of a module for use in Storybook but I can only do it with JavaScript and CJS imports, not TypeScript and ESM. My current webpackFinal contains this
config.resolve.alias['moduleToMock'] = require.resolve('../src/mocks/mockModule')
return config;
This current config doesn't work with TypeScript and will throw an error saying that the mock module can't be found. How can I configure this to work with TypeScript?
In general TypeScript only throws errors when you try to compile the code. If you encounter an error on code execution this is very likely more related to your code rewrite. If the webpackFinal of the Storybook already supports ESM and you need to import the module synchronously then you can create a replacement for the require function like this:
import { createRequire } from 'module'
const require = createRequire(import.meta.url)
...
config.resolve.alias['moduleToMock'] = require.resolve('../src/mocks/mockModule')
Hope it helps.

How to re-use a React library with hooks

I'm writing my own library to help building forms with React.
The goal is to be able to re-use it in any React application (made from scratch, with create-react-app, nextjs, other ?)
My problem is that I can't firgure out how to re-use it.
Here is the first issue I encountered when I tried to reuse my library in another project :
Invalid Hook Call Warning
React says that the reason could be one of the following :
You might have mismatching versions of React and React DOM.
You might be breaking the Rules of Hooks.
You might have more than one copy of React in the same app.
After investigation, I've excluded points 1. and 2.
I was using Parcel in the first place to build my library but I needed to exclude React from the bundle to solve 3.
That's why I switched to Webpack and moved the React dependency to the peerDependencies + devDependencies.
I've tried different webpack configurations :
const config: webpack.Configuration = {
...
externals: {
react: 'React'
}
}
--> which leads to the following error in the consuming application :
React is not defined
const config: webpack.Configuration = {
...
externals: {
react: {
root: 'React',
amd: 'react',
commonjs: 'react',
commonjs2: 'react',
umd: 'react',
}
}
}
--> which leads to the following error :
Cannot read property 'createContext' of undefined
I've tried to use my library with npm link and also by publishing it on npm but the result is the same.
Step to reproduce :
Install #mlaopane/formhook in your react application (npm i #mlaopane/formhook or yarn add #mlaopane/formhook)
Try to use a component, for example
import { Form } from '#mlaopane/formhook'
export default function App() {
return <Form />
}
You should see the error in the console
Thank you for helping me with this :)
NB: This is my first issue, please tell if more information is needed.
I've finally found a solution, inspired by create-react-library.
It looks like Rollup is a better candidate for bundling React libraries.
Even if I still can't link my library locally, it can be used when published.

React Bundle giving error: "Type Error: cannot read property 'ReactCurrentOwner' of undefined"

For the deployed versions of my app, I have added the following code to my Webpack config to grab React from a vendor bundle that I serve:
externals: {
react: 'vendor.React',
'react-dom': 'vendor.ReactDOM',
},
This usually works but for some reason now I am getting the error:
Type Error: cannot read property 'ReactCurrentOwner' of undefined
Does anyone know what this error is or why my minified react bundle would throw this error?
React Version 16.5.2
Shoutout to #Demon for trying to help out. Eventual solution was as follows:
I was using the CDN version of React which I downloaded locally on my file-system since I was trying to serve two different versions of React from this micro-service. Turns out the CDN version or React-Dom has require statements:
var react = require("react");
Those require's were resolving to my node_modules which had a lower version of react. The fix was to manually edit those to point to the local filesystem version of React I had downloaded.
var react = require("./react.development.js")

Webpack + Angular2 AOT: Uncaught SyntaxError: Unexpected token import

in this set-up, how do you transpile the angular2 library being imported from the generated ngfactory files?
the current app is a combination of the webpack + aot cookbook based on the angular docs
angular.io/docs/ts/latest/cookbook/aot-compiler.html
angular.io/docs/ts/latest/guide/webpack.html
I have a working POC where you can replicate the issue from this repo:
https://github.com/jetlogs/Angular2-AOT-Localization
after you've done the compilation / bundling, you can open the 2 files:
non-aot.html - this is the non-aot version of the same app, and it loads fine
aot.html - this file fails with:
ng_module_factory.js?95b1:13 Uncaught SyntaxError: Unexpected token import
Expected behavior
the expected behavior is that aot.html and non-aot.html should have the same behavior
Minimal reproduction of the problem with instructions
clone the repo, then
run these commands on the working directory:
npm install
npm postinstall
npm run build
then open aot.html to reproduce the issue
Is there any way on how to fix the import statements from the imported angular2 libraries? Thanks
UPDATE:
I've tried transpiling the angular2 source files which are in ES2015 by using the babel-loader:
{
test: /\.js$/,
loader: 'babel',
include: [
/node_modules(\\|\/)#angular/
],
exclude: [
/\.umd\.js$/
],
query: {
presets: ['es2015']
}
},
it now compiles without issues with ES6 incompatibilities, however, it now encounters a new error only for aot.html:
core.umd.js?e2a5:3272Uncaught Error: No provider for NgZone!
any reason why transpiled angular2 source codes being referenced by the AOT compiler are cdausing NgZone issues?
I've updated the repo above to reflect my latest changes
UPDATE2: 10/13/16
Updated to Angular 2.1
still the same issue
The System.import syntax used in ng_module_factory.js is ES6 style module loading. Webpack 1, which you are probably using, does not support this syntax.
A workaround might be to transpile the Angular ES6 modules to ES5 with require() syntax, but you already tried this without success.
However you might consider switching to Webpack 2, which fully supports ES6 style imports and is very close to its stable release. The compilation worked for me this way without changing anything except for the webpack config which uses a new syntax for some parts.
For me it was a wrong import generated by IDE:
import { Component, Output } from "#angular/core/src/metadata/directives";
Instead of:
import { Component, Output } from "#angular/core";

SystemJS with Typescript conflict?

I am trying to configure SystemJS for an existing AngularJS + Typescript application.
I have a problem with module loading:
When I use this syntax:
import module1 from './path-to-module1'
TS compiler is happy but SystemJS will not find this module. After a little investigation I found this, on SystemJS documentation:
System.defaultJSExtensions = true;
// requests ./some/module.js instead
System.import('./some/module');
Cool, now both TS compiler and SystemJS work. But, SystemJS documentations says:
Note that this is a compatibility property for transitioning to using explicit extensions and will be deprecated in future.
So, I figured out that I should add a .js extention to my module loading, like this (removing the 'defaultJSExtensions = true' flag):
import module1 from './path-to-module1.js'
Now SystemJS knows how to load my module, by TS compiler says:
Cannot find module './path-to-module1.js'
How can I make TS figure this out? Should I manually add all my modules to a *.d.ts file? How?
10x!
EDIT
I found this post, which I guess should be what I need to do. I found this on my Grunt file:
typescript: {
build: {
src: ...,
outDir: '...',
reference: 'reference.ts',
options: {
target: 'es5',
sourceMap: false,
declaration: false,
removeComments: false,
experimentalDecorators: true,
module: 'commonjs'
}
}
}
But, changing the commonjs to system did not help hree..
Don't worry, the SystemJS documentation is a bit misleading... Once they remove the defaultJSExtension all you have to do it to mark your code directory as a package (In the systemJS configuration) You can read about it here
Anyway, the file name without the extension is a valid ES6 module import syntax, so SystemJS will have to support it, as I said they will support it using a different way in the configuration.

Resources