Import module in React component for publish on NPM - javascript

It's my first React component for publication in NPM. I use react-webpack-component package from Yeoman to start my project. But when I install and import my component to React app, I catch error:
Failed to compile.
Error in ./~/kladrapi-react/index.js
Module not found: [CaseSensitivePathsPlugin] `/develop/myproject/node_modules/kladrapi-react/node_modules/React/react.js` does not match the corresponding path on disk `react`.
# ./~/kladrapi-react/index.js 1:82-98
I'm understand this error, but not understand how correctly import React modules to my component!
Actual version on GitHub

I think there are multiple issues in your code.
In index.html:
#line-- <script src="kladrapi-react.js"></script>
The file name is "kladrapi-react.jsx" not "kladrapi-react.js".
Second issue, here you are expecting "kladrapi-react.js(x)" to be on root level. Which is not the case. According to your folder structure "kladrapi-react.js(x)" file is at ./lib/kladrapi-react.jsx.
Apart from this, in your kladrapi-react.js(x) file you have mixed ES5 and ES6 syntax. You are accessing the variable KladrapiReact in index.html but you haven't exported it as 'KladrapiReact'. I would recommend you to put 'React.createClass....' code in a separate component.
For the error you are receiving you need to use 'case-sensitive-paths-webpack-plugin':
This Webpack plugin enforces the entire path of all required modules match the exact case of the actual path on disk.
npm install --save-dev case-sensitive-paths-webpack-plugin
Usage:
var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
var webpackConfig = {
plugins: [
new CaseSensitivePathsPlugin()
// other plugins ...
]
// other webpack config ...
}
For more info on this plugin read documentation here.

Module not found: [CaseSensitivePathsPlugin] /develop/myproject/node_modules/kladrapi-react/node_modules/React/react.js does not match the corresponding path on disk react.
# ./~/kladrapi-react/index.js

Related

Cannot import Node, JS, or Electron library in Angular Typescript module no matter what I try

I'm fairly new to stack overflow, so if I don't ask the question correctly feel free to help me out.
I've scoured every stack overflow and google article I can find and nothing works to import Electron, any other Node modules, or any native JS modules--I can only import and use Angular/typescript modules. I'm trying to import electron and use it in an angular app. I am also trying to use __dirname. For electron I've tried:
const { remote } = require('electron');
const { remote } = (<any>window)require('electron');
import { ipcRenderer, BrowserWindow, electron } from 'electron';
import * as remote from '#electron/remote'
For __dirname I've tried:
import * as fs from 'fs';
import { readFileSync } from 'fs';
import readFileSync from 'fs';
and for the implementation:
import.meta.url
process.cwd()
__dirname //worth a shot I guess
I've combined these options, and nothing works. I've run npm install --save-dev #types/node, and when that didn't work tried deleting the node_modules folder and ran npm install. "types": ["node"] has already been added to tsconfig.json's compilerOptions.
Here is one of my errors:
Error: src/app/electron/electron.service.ts:3:20 - error TS2591: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i --save-dev #types/node` and then add `node` to the types field in your tsconfig.
3 const { remote } = require('electron');
~~~~~~~
I've already installed #types/node. It also almost always posts the following error. I have no clue what it's for, as it shows even when I'm not importing 'fs'.
Error: ./node_modules/electron/index.js
Module not found: Error: Can't resolve 'fs' in '/Users/user/Programming/Git/project/node_modules/electron'
resolve 'fs' in '/Users/user/Programming/Git/project/node_modules/electron'
Parsed request is a module
using description file: /Users/user/Programming/Git/project/node_modules/electron/package.json (relative path: .)
Field 'browser' doesn't contain a valid alias configuration
resolve as module
looking for modules in /Users/user/Programming/Git/project
using description file: /Users/user/Programming/Git/project/package.json (relative path: .)
Your browser cannot run modules written in C++ like fs and electron. Node.js can do it because node developers specifically created node to be able to load binary modules (written in C++). Browsers can only run javascript modules.
As such builders such as Webpack ignore these modules simply because it does not make sense to include them.
You cannot use fs and electron in your Angular app. You can however use Angular in your electron app (because electron was created to run javascript code and Angular compiles to pure javascript code).
Trying to use fs or electron in Angular is a little bit like trying to import Internet Explorer or Adobe Photoshop in Angular.

Dynamically import React component from external URL and use parent React environment

I have a Main UI into which I want to load a Sub UI in the form of a React Component, which is then integrated through a React.Suspense JSX Tag. The Main and the Sub UI will both be separately bundled with Webpack. The Sub UI is bundled as a Webpack 5 Module Library.
Now, the dynamic loading of the component from an URL seems to be no problem. I can use
var path = "<< some URL to a JS-File in a CDN >>";
var SubUiComponent = React.lazy(() => import(/* webpackIgnore: true */ path));
But because the component that I want to import is bundled with Webpack, another React instance is being used. I have already tried to use Webpack Externals, but there seems to be no way that it can be used in combination with dynamic imports.
When I'm not defining externals, I get the following error:
Uncaught Error: Invalid hook call. Hooks can only be called inside of
the body of a function component. This could happen for one of the
following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app See https://reactjs.org/warnings/invalid-hook-call-warning.html for tips
about how to debug and fix this problem.
With externals defined in webpack.config.js, I get the expected error:
Uncaught ReferenceError: React is not defined
So, is there a way of bundling a React component "kind of" as a library and then import it into another React Environment and use it there?
With two of your different local react projects, you want to link/refer/import one from another? If this is what you're trying to do then yes, it is possible.
First Approach:
You need to research on npm link
Note that package-name is taken from package.json, not from the directory name.
npm link in a package folder will create a symlink in the global folder {prefix}/lib/node_modules/<package> that links to the package where the npm link command was executed.
It will also link any bins in the package to {prefix}/bin/{name}. Note that npm link uses the global prefix (see npm prefix -g for its value).
In some other location, npm link package-name will create a symbolic link from globally-installed package-name to node_modules/ of the current folder
cd ~/projects/some-dep
npm link # Step 1.
cd ~/projects/my-app
npm link some-dep # Step 2.
now, from your my-app folder, you can install some-dep
~/projects/my-app
npm install some-dep#
Second Approach:
Bundle and publish your project to npm registry then install, import it into your other project. Refer this one that I'd published to try out
Third Approach:
Webpack ModuleFederation, when you import the project/module, it will look for it in node_modules, if not found then in the federated modules.
Ref: https://webpack.js.org/concepts/module-federation/

How to import nodejs module "module" via es6 import to create "require" function with "createRequire" in order to use node's "require"?

I am writing a JavaScript es6 module which contains "Mocha" test-cases which test a JavaScript es6 module containing the actual functionality of my app.
I am trying to import nodejs module "module" via es6 import like so:
import { createRequire } from 'module';
Next I create a "require" function by calling "createRequire":
const require = createRequire(import.meta.url);
Afterwards I try to use "require" to import nodejs modules:
const chai = require('chai');
const assert = chai.assert;
I put that all together in a HTML file, started a web-server and opened the HTML file in the browser.
Unfortunately, the first line gives me an error in the console of the Browser Firefox:
TypeError: Error resolving module specifier: module
The browser Chromium gives me the following error message:
Uncaught TypeError: Failed to resolve module specifier "module". Relative references must start with either "/", "./", or "../".
Actually, giving relative references is not working either:
I installed the nodejs module "module" (npm install module) and used a relative path to that module. Unfortunately, the browser does not know how to load the module because no concrete entrypoint is given.
I just tried stick to the manual but had no luck:
https://nodejs.org/api/modules.html#modules_module_createrequire_filename
What do you think? How should I change my code so that this works?
Many thanks in advance for your valuable advice.
I hope you've installed the module using 'npm install module' command, try using commonJS pattern and include the module in the following way
const { createRequire } = require('module');
require() is used to load files in node, and module is a node module.
These things don't exist in browsers.
You do these things, and running mocha tests in node. There should be no browser, just a command line.

react or npm issue: Module not found: [CaseSensitivePathsPlugin] `...\react.js` does not match the corresponding path on disk `react`

I'm getting the following errors when I execute the npm start command on a react project.
Failed to compile.
Error in ./~/react-scroll-pagination/dist/index.js
Module not found: [CaseSensitivePathsPlugin] `C:\Users\timhu\Dev\MongoDbStitch\PlateSpace\Web\node_modules\React\react.js` does not match the corresponding path on disk `react`.
# ./~/react-scroll-pagination/dist/index.js 3:27-43
Error in ./~/react-scroll-pagination/dist/index.js
Module not found: [CaseSensitivePathsPlugin] `C:\Users\timhu\Dev\MongoDbStitch\PlateSpace\Web\node_modules\jQuery\dist\jquery.js` does not match the corresponding path on disk `jquery`.
# ./~/react-scroll-pagination/dist/index.js 3:45-62
I'm new to react - but from what I can tell it's a pathing issue where npm install adds modules into the node_modules folder, all with lowercase folder names, but the compiler resolves to folder names with mixed case paths.
How do I fix this? The code is from the MongoDb Stitch PlateSpace tutorial project
Do I updated the existing code (maybe the import statements) or is it a npm or react issue?
Thanks
Tim
I come across the same problem.
I replaced :
import React, {Component} from 'React', with :
import React, {Component} from 'react'.
React is case-sensitive, so be careful and good luck.
For anyone facing this issue who is using CRA, I was getting this error and was not understanding why. My VS Code clearly showed the correctly named file, so I decided to check in the terminal:
ls -la [path/to/file/location]
I then actually saw that the file was in fact lowercase!
I renamed the file via the terminal and re-listed it to confirm:
mv src/create_page/createPage.jsx src/create_page/CreateDashboard.jsx
ls -la [path/to/file/location]
This fixed my issue, so at the end, I am not sure why this happened, maybe because my VS Code was not autosaving before I set the settings flag.
Solved it...
I haven't import all the libraries. So, I went to my root folder and excecute.
npm install
then
npm start
You may be executing the npm install / start inside of the wrong folder. I would delete the current directory and make sure to run the install in:
cd /stitch-examples/helloworld/react-example/
then
npm install
npm start
For this error :
import React from 'react'; in your index.js file . For this error : Error in ./~/react-scroll-pagination/dist/index.js
Module not found: [CaseSensitivePathsPlugin]C:\Users\timhu\Dev\MongoDbStitch\PlateSpace\Web\node_modules\jQuery\dist\jquery.jsdoes not match the corresponding path on diskjquery.
replace this code import React from 'react'; in your index.js file .
For this error :
Error in ./~/react-scroll-pagination/dist/index.js
Module not found: [CaseSensitivePathsPlugin]C:\Users\timhu\Dev\MongoDbStitch\PlateSpace\Web\node_modules\jQuery\dist\jquery.jsdoes not match the corresponding path on diskjquery.
replace the code with import Jquery from './jquery';
Don't worry this errors will shows pretty commonly its because react is a case sensitive.
For me the issue was the files on my disk was named filename.js, but my imports were doing this import thing from 'fileName.js'.
Renaming the file from filename.js to fileName.js on disk fixed the issue.

Import from subfolder of npm package

I've been working on creating a small library of React components for use in several other projects. I am publishing the package internally (using a private GitHub repository) and then including in another project. However, when I go to import from a subdirectory of the package I am not able to do so as the paths don't match.
The projects using the package all utilize webpack to bundle/transpile code as I am trying to avoid doing any building in the component library if possible.
Directory Structure
- package.json
- src/
- index.js
- Button/
- index.js
- Button.jsx
- ButtonGroup.jsx
- Header/
- index.js
- Header.jsx (default export)
package.json
...
"main": "./src/index.js",
"scripts": "",
...
src/Button/index.js
import Button from './Button';
import ButtonGroup from './ButtonGroup';
export default Button;
export { Button, ButtonGroup};
src/index.js
Is this file actually necessary if only importing from subdirectories?
import Button from './Button';
import ButtonGroup from './Button/ButtonGroup';
import Header from './Header';
export { Button, ButtonGroup, Header };
Other Project
// This project is responsible for building/transpiling after importing
import { Button, ButtonGroup } from 'components-library/Button';
Example
Material-UI is a library of React components that is used by requiring in the following fashion: import { RadioButtonGroup } from 'material-ui/RadioButton. I've tried to figure out how this works for them but to no avail yet.
Similar Questions
How would I import a module within an npm package subfolder with webpack?
This is very nearly the correct approach I require, except that the import path used there involved the src/ directory, which I am trying to avoid (should be component-library/item, not component-library/src/item (which does work currently though))
Publishing Flat NPM Packages
This is exactly what I want except that I was hoping to not have a "build" phase in the package (rely on importing locations to build/transpile)
Questions
Can I skip the src/ directory somehow in the import path?
Can I skip any type of build phase in the package (so developers don't have to build before committing)?
How does a package similar to material-ui handle this?
Can I skip the src/ directory somehow in the import path?
Yes. Using the package.json "exports" field, which should be supported by Webpack in a near future (see this issue), but has already been supported by Node since Node 12 LTS following the Bare Module Specifier Resolution proposal:
package.json
...
"main": "./src/index.js",
"type": "module",
...
"exports": {
"./Button": "./src/Button/index.js",
"./Header": "./src/Header/index.js"
},
...
Now, the following code:
// This project is responsible for building/transpiling after importing
import { Button, ButtonGroup } from 'components-library/Button';
should be translated to:
import { Button, ButtonGroup } from 'components-library/src/Button/index.js';
which should correctly import the requested modules.
Caveat
Now, it would certainly be tempting to try a simpler version like:
...
"exports": {
"./Button": "./src/Button/",
"./Header": "./src/Header/"
},
...
so as the usual import statement
import { ... } from 'components-library/Button';
gets translated to
import { ... } from 'components-library/src/Button';
This looks nice, but it will not work in this case, because your submodules don't have each their own package.json file but rely on their index.js file to be found.
/!\ Unlike in CommonJS, there is no automatic searching for index.js or index.mjs or for file extensions.
src/index.js - Is this file actually necessary if only importing from subdirectories?
I don't think so, but you can keep it if you want.
Can I skip any type of build phase in the package?
Using the "exports" field does not require you to transpile your code.
The answer may depend on how you installed your components library. If you did it via either npm install <git-host>:<git-user>/<repo-name> or npm install <git repo url>,
You should be able to import {Button} from 'component-library/Button' as is, according to your first linked question. Similar to Node's require() resolution, Webpack should resolve subdirectories within component-library relative to component-library's entry point. You can find the docs on customizing the resolution behavior via the webpack.config.resolve property. material-ui seems to rely on resolving subdirectory imports from the module entry directory.
To distribute an ES module library, there's no need for building before distribution. However, projects such as create-react-app may need a pre-transpiled version.
Alternately, you can write import {Button} from 'components-library'.
Webpack will trace the dependencies back through each index without a fuss.
you have to install babel-plugin-module-resolver package
Specify the package relative path in your .babelrc file alias like this
{
"plugins": [
["module-resolver", {
"alias": {
"components-library": "./node_module/components-library"
}
}]
]
}
then you can import subdir of npm package like this
import { Button, ButtonGroup } from 'components-library/Button';
One of the possible solutions there is webpack aliasing system.
You can create another project, call it for example 'app-aliases', so your aliases will be reusable.
This project will has one js file with all of your packages paths:
const path = require('path');
module.exports = {
'#components': path.resolve(__dirname, 'node_modules/components-library/src'),
'#another': path.resolve(__dirname, 'node_modules/any/path/you/want'),
}
And then add it to the webpack configuration in any project which will be responsible for building/transpiling:
webpack.config.js
const appAliases = require('app-aliases');
const config = {
...
resolve: {
alias: {
...appAlises
}
}
}
In the runtime code you will be able to use it like this:
import {Button} from '#components/Button';
import {Something} from '#another'
If you are using typescript you will need to add the same aliases to the paths tsconfig property.
So answers to your questions are:
Yes, you can use any path in aliases
Yes, it is not necessary to build all of your projects
I see that now mui uses imports from directi packages (core for example), see https://material-ui.com/components/radio-buttons/ there is import Radio from '#material-ui/core/Radio';. But I hope they using re-export that I described below.
Also about node.js resolution mechanism.
When you import some library it tries to find node_modules/some-library/package.json and then main property inside it. This property should lead to your main entry point. Usually it is src/index.js (you should set it in package.json if it is no there yet). In this file you can re-export anything you want from internals file structure and will be able to use it without the full path.
Please see this repo for some examples.
I'am an angular developer never used react but what I could tell that material-ui are using monorepo where same concept exists in angular where we create one workspace and this workspace hold multiple project/packages as named in react. for more info Workspaces with Yarn
Material-ui using fake paths in tsconfig to make it appears like src folder doesn't exists this from the git you provided: tsconfig.json
This is possible but requires publishing a curated dist folder rather then the root of your project.
The whole thing is rather simple if you understand how module resolution works, and you just need a small script to prepare your distribution.
Lest I repeat all the details here, please see my answer for Importing from subfolders for a javascript package.

Categories

Resources