Can't resolve error appears only in my webpack-build - javascript

I'm trying to import a module _module_name_ into my current react-project with typescript, say react-app for reference. The project is bundled up with webpack. I'm importing it into one of my .tsx components. The module that I am importing was written by me and I published it on npm. I'm getting a cannot resolve error when building my react project. It cannot resolve the fs module, apparently. I wonder what causes this problem? Here is the error output:
ERROR in ./node_modules/_module_name_/index.js 2:11-24
Module not found: Error: Can't resolve 'fs' in
'/path/to/project/node_modules/_module_name_'
resolve 'fs' in '/path/to/project/node_modules/_module_name_'
Parsed request is a module
using description file: /path/to/project/node_modules/_module_name_/package.json (relative path: .)
Field 'browser' doesn't contain a valid alias configuration
resolve as module
The _module_name_ is extremely simple. For all practical purposes it looks like this:
// index.js
const path = require('path')
const fs = require('fs');
function foo() {
const abi = JSON.parse(fs.readFileSync('file.json', 'utf8'));
return abi
}
module.exports = {
foo
};
Then I have a typescript declaration file:
// index.d.ts
export function foo(): any;
Of course I have the file itself:
// file.json
{
"a": 1
}
and I have a package.json in that _module_name_ which contains at least the following entries:
// package.json
{
"main": "index.js",
"types": "./index.d.ts",
"dependencies": {
"fs": "^0.0.1-security",
...
}
...
}
Remark: When I am in my react project react-app I have no problems importing foo in any old javascript file or typescript file. It will work perfectly unless it's part of the react app. How strange is that. Maybe it has to do with my webpack loaders, cause I'm using webpack to bundle the app.
Question: Is the problem on the side of the _module_name_ or on the side of the react-app?

just had a quick read, but basically you are trying to use nodeJS in the browser. that's not a good idea. have a look here: Can't resolve 'fs' using webpack and react
requiring the files and then parsing should work

Related

Mark file imported by the main file in an ES6 Node.JS project as a module too?

I just went through the discomforting import vs. require time suck that many of us go through, trying to use both ES6 and CommonJS files in the same project, in a stand-alone Node.js utility I am working on.
I did find the the following solutions that you (hopefully) find at the end of a lengthy Web/Stack Overflow session:
Change the extension of the main file to ".mjs"
OR: Add type: "module" to the project's package.json file
Then add these two lines of alchemy to your project to get back the use of require:
import {createRequire} from "module";
const require = createRequire(import.meta.url);
That all works. Unfortunately, I have legacy files with ".js" extensions in the project that are actually modules. They use the import statement and they also export symbols. This leads right back to that annoying "cannot use import outside a module" error when I ry to run the utility.
Is there a way to use package.json to mark those included files too as modules? I am really loathe to change their extensions to ".mjs" because they are used by a lot of projects and that would lead to fairly massive GitHub headache.
If not, is there some other way to solve this problem?
----- SOURCE CODE SNIPPETS ----
My package.json file for the utility:
{
"name": "utility",
"main": "inspect-animation-model-data-file.js",
"type": "module"
}
Here is the code that imports the problem file (FBXLoader.js), with the createRequire alchemy statements shown:
import {createRequire} from "module";
const require = createRequire(import.meta.url);
import FBXLoader from "../public/javascripts/threejs/examples/jsm/loaders/FBXLoader.js";
Here are the elements in FBXLoadder.js that trigger the "cannot use import" error.
import {
AmbientLight,
AnimationClip,
...
// And...
export { FBXLoader };

node-fetch 3.0.0 and jest gives SyntaxError: Cannot use import statement outside a module

I'm trying to upgrade my api to use node-fetch 3.0.0. Part of the breaking changes in their documentation is that node-fetch is now a pure ESM module.
https://github.com/node-fetch/node-fetch/blob/main/docs/CHANGELOG.md
My unit tests have started breaking from this change. I was using jest.requireActual("node-fetch") for the Response object
const { Response } = jest.requireActual("node-fetch");
However, with the new change, I get:
"Property 'Response' does not exist on type '{}'."
I tried changing to an import statement which seems to fix that error:
import { Response } from "node-fetch"
Now, I get the following error when I run my unit tests:
Test suite failed to run
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
C:\Users\{mypath}\api\node_modules\node-fetch\src\index.js:9
import http from 'http';
^^^^^^
SyntaxError: Cannot use import statement outside a module
2 | import { AuthProvider, TokenCache } from "./tokenTypes";
3 | import { getUserEmail, getUserId, getUserRole } from "../common/authUtil";
> 4 | import fetch from "node-fetch";
The error seems to be occurring within node-fetch itself.
I tried changing the test script in my package.json to match what the jest documentation suggests for ESM modules. https://jestjs.io/docs/ecmascript-modules
package.json
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
The documentation also suggests changing the transform property in jest.config.js to take an empty object, but my transform object looks like the following for typescript and ts-jest:
jest.config.js
transform: { "^.+\\.ts?$": "ts-jest" }
If I change this to an empty object all of my tests break. I'm not very familiar with CJS vs ESM, so any help would be appreciated.
Fetch 3.0 is designed for using esmodules instead of commonjs. Therefore you have to make sure you import it into a module.
For example: to import it to app.js : Add "type":"module" in your package.json and then import it.
For importing it to other files or app.js even, you can also change the extension from .js to mjs that will tell nodejs to treat as a esmodule.
Otherwise downgrade fetch to use an older version that supports commonjs like 2.something.
npm install node-fetch#2
npm install #types/node-fetch#2
I had the same problem!
adding
transform: {
"^.+\\.(ts|tsx)$": "ts-jest",
"^.+\\.(js)$": "babel-jest",
},
transformIgnorePatterns: [
],
to my jest.config.js file solved it.
and btw these are my versions:
"jest": "^27.3.1",
"ts-jest": "^27.0.7",
"node-fetch": "^3.1.0"

How does webpack pick a relative path inside node_modules ? does it reference package.json at all?

When i do npm install react-slick, i get the following in my node_modules folder:
Now in my react application in a src/index.js file, when i do the following:
import Slider from "react-slick";
How does webpack know where to pick slider from ? will it at all look for some clue or definition inside node_modules/react-slick/package.json at all ?
Edit :- so here is the package.json file for webpack, when i import Slider from 'react-slick' , does it resolve to dist or lib ? and which file does it pick then and why ?
Well, the simple walkthrough of it will be as below:
Simple Walkthrough
If you carefully look at the node_modules/react-slick/package.json there is a property named main. Something like this:
{
"name": "react-slick",
"main": "index.js"
}
It will tell the Webpack which file is the entry file of the whole package (It's usually referred to index.js). All the necessary exports for the package lies in this file, so Webpack will only look for those exports and will import what you looking for. In this particular case, there should be a default export for the Slider that you using right now. So the index.js is probably something like this:
// index.js
var slider = require('./lib/slider'); // Usually all the main modules are lies under lib folder.
// other imports ...
module.exports = slider;
Difference between lib and dist
Usually, the dist folder is for shipping a UMD that a user can use if they aren't using package management. The lib folder is what package.json, main property points to, and users that install your package using npm will consume that directly. The only use of the lib as opposed to src is to transform your source using babel and Webpack to be more generally compatible since most build processes don't run babel transforms on packages in node_modules.
Webpack uses aliases to target node_modules using a shorthand.
Example #1:
import 'xyz'
/abc/node_modules/xyz/index.js
Example #2:
import 'xyz/file.js'
/abc/node_modules/xyz/file.js
Once it targets the correct folder in node_modules, it follows the rules written in the package itself (manifest, package.json)
You can also define your own aliases as such:
webpack.config.js
const path = require('path');
module.exports = {
//...
resolve: {
alias: {
xyz$: path.resolve(__dirname, 'path/to/file.js')
}
}
};
And then can be used as import xyz from $xyz

Webpack can't find import needed for Typescript type resolution. How to fix this?

My project uses typescript and built with webpack.
I have a typings file that comes from a third part lib located under node_modules/#types/libname/custom.d.ts. That file has a namespace declaration with a few types in it:
declare namespace MyNamespace {
export type A = ...;
}
Then in order to be able to use that type in my typescript code like so:
const x: MyNamespace.A;
...I need to add the import declaration as follows somewhere in the app:
import 'libname'
Which tsc resolves correctly to node_modules/#types/libname/custom.d.ts so everything works if I compile with tsc.
However webpack then can't build. It can't understand this import:
ERROR in ./Index.tsx
Module not found: Error: Can't resolve 'libname' in 'C:\<path_to_index_file>'
# ./Index.tsx 44:0-32
I tried to add an alias in my webpack.config like so:
resolve: {
alias: Object.assign({
'libname$': path.resolve(__dirname, 'node_modules/#types/libname/custom.d.ts'),
}
},
But then it fails because it can't understand that file's syntax and asks if I'm missing a loader.
How can I fix this so that webpack will understand this typings import statement?
I'm on webpack version 4.41.6
Thanks!
You should use the null-loader for this import so webpack will ignore it.

Trouble using babel transpiler with WebPack

I'm trying to use this package in my application.
It appears to be written in ES6 so I need a transpiler like babel. I've started a new project and tried the following:
Create new index .html / .js file for testing.
npm install audio-effects
npm install gulp gulp-babel babel-preset-es2015
Create .babelrc
After trying to run this from the dist folder with python -m SimpleHTTPServer, I got an error: index.js:3 Uncaught ReferenceError: require is not defined.
After some digging, this is because require can't be used client-side. So next I looked into using WebPack to allow me to use require.
I went into my dist folder (where my transpiled javascript is) and ran:
webpack ./index.js index.js
But now I'm getting the error index.js:78 Uncaught SyntaxError: Unexpected token import.
Can anybody see what I'm missing (apart from a NPM-ES6-Gulp-WebPack tutorial)? I seem to be stuck in a loop of WebPack-ing and transpiling.
index.html
<!DOCTYPE html>
<html>
<body>
<h4>Welcome</h4>
<button onclick="startAudio()">Start Audio</button>
<script src="js/index.js"></script>
<script type="text/javascript" src="bundle.js" charset="utf-8"></script>
</body>
</html>
index.js (pre-babel / WebPack - ification)
import {HasAudioContext} from 'audio-effects';
function startAudio() {
console.log("Start Audio...");
let audioContext = null;
if (HasAudioContext) {
console.log("Has Audio CTX");
audioContext = new AudioContext();
}
else {
console.log("No Audio CTX");
}
}
gulpfile.js
var gulp = require("gulp");
var babel = require("gulp-babel");
gulp.task("default", function () {
return gulp.src("src/app.js")
.pipe(babel())
.pipe(gulp.dest("dist"));
});
I've made some changes to the library (I'm the original author of the package). When installing the package with npm, you will now get the transpiled ES5 code instead of the ES6 source. You'll still need webpack, browserify, ... to load the module though.
This might fix the the Uncaught SyntaxError: Unexpected token import error, so please update your audio-effects library to the latest version.
The wrong imports as mentioned in the answer by Jorawar Singh should be resolved as well.
I'm still working on the library so if you run into any problems, feel free to create an issue or pull request on github.
I personally use the package with webpack. this is my webpack.config.babel.js file (remove comments).
Note: I'm using react, if you don't set the react parameter to false.
import config from 'madewithlove-webpack-config';
export default config({
react: true,
sourcePath: 'src', // Source directory
outputPath: 'builds', // Transpiled coded directory
});
This imports a basic webpack config from https://github.com/madewithlove/webpack-config/
Since I'm writing code in ES6, I'm transpiling it with babel, my .babelrc file looks like this:
{
"presets": ["es2015", "stage-0"],
}
With all this setup, you can just run webpack with webpack-dev-server --inline --hot.
You don't have to use the madewitlove webpack config but it takes care of some standard setup like compiling scss etc.
I hope this gives you an insight in how to use the audio-effects package or any other ES6 package.
Well what i understand there was some issues with this library it was written es6 and when you do import and want to complie into es5 with webpack then webpack will also bummbel all the require modules for you. Here's my webpack.config look likes
var webpack = require('webpack');
var config = {
entry: './index.js',
output: {
path: __dirname + '/dist',
filename: 'bundle.js'
},
module: {
loaders: [ {
test: /\.js$/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}]
}
};
module.exports = config;
running by webpack will compile the library and your index.js file to bundle.js
there was some other issues i think in order to get this library you need to do some small changes in library.
from
'./Helpers/HasAudioContext'; //this doesn't exist and
//webpack will give you compile error
to
'./helpers/hasAudioContext';
I had one issue whitch i couldn't resolve is i couldn't run the startAudio function but through the index.js i could (weard let me know if you find why)
in your index.js
document.getElementById("btn").addEventListener("click", startAudio);
there are still some issues witch i want to resolve and also there are some issues with the library witch need to be resolved

Categories