Webpack: Make dependency using another dependency instead of its own subdependency - javascript

I am using webpack to build my app and I use a library (eventemitter4) that itself depends on another library (underscore).
However, I am already using in my application an alternative to underscore (lodash and more exactly the es6 version).
I would like eventemitter4 to use this later library and avoid including in my build the two.
I install my dependencies using npm install. As a result, underscore is bundled as a subdirectory inside the eventemitter4's directory.
It tried to set aliases but I could not make it work:
alias: {
"underscore": "lodash-es",
"lodash": "lodash-es",
"~/underscore": "lodash-es"
}
raises
ERROR in ./~/eventemitter4/index.js
Module not found: Error: Cannot resolve module 'lodash-es' in /Users/me/myapp/node_modules/eventemitter4
# ./~/eventemitter4/index.js 6:2-23
If I do not add "~/underscore": "lodash-es", the sub-underscore is included instead of lodash.
Any idea?
Thank you very much for your help.

I actually found the reason. The alias was working. The cause of the error was that lodash-es does not provide a main attribute in his package.json (it only provides an esnext:main which is not recognised by webpack).
I solve the issue by using:
alias: {
"underscore": "lodash-es",
"lodash": "lodash-es/lodash",
"~/underscore": "lodash-es"
}

Related

Force nested npm dependency to use same one

I am facing an error that caused by lower version of TypeScript, root cause is I update prettier version, related post: https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/60310
So dependency issue was:
React -> TypeScript#4.7.4
Other-library -> Webpack-dev-server -> TypeScript#3.8.2
Prettier -> TypeScriptv4+
Since Prettier require TS version 4+ and the Webpack-dev-server has a version of 3.8.2, that will cause the program to throw error.
I can not change the version of Other-library, but I still need the version of TypeScript to be v4+
I am looking at this post:How do I override nested NPM dependency versions?
This seems does exactly what I needed to do.
But after I use the overrides property in package.json, I do see React is pickup the TypeScript version 4.7.4,
howerver I get the following error:
Child process failed to process the request: Error: Debug Failure. Palse expression. at resolveNamesWithLocalCache, at typescipt/lib
Thanks
My package json looks like:
{
"devDependencies": {
"typescript": "^4.7.4"
},
"overrides": {
"webpack-dev-server": {
"typescript": "$typescript"
}
}
}
`
So I checked, typescript is only "devDependencies" to webpack-dev-server. It's NOT supposed to be installed at all. How did you even end up in this situation šŸ˜‚
It must be something about the way you install those packages. I don't know what happened, just try remove node_modules folder entirely, and also package-lock.json, then npm install again. You don't need that "overrides" field.
Additionally, it sounds to me this whole mayhem starts because of #types/prettier. HOWEVER, unless you have a very specific use case (which I seriously doubt) that requires integrating with prettier's programmatic API, through hand written TS code, you don't even need #types/prettier in the first place. Just get rid of that troublemaker. All #types/* packages are optional.

how can I setup #types for a third party react javascript module so I can access it from typescript and package it with webpack?

There is a 3rd party all-javascript npm scoped package, let's call it #foo, with a module inside called bar. I wanted to use the react component #foo/bar/X from within my typescript .tsx file. I immediately ran into "module not found" when I tried to import X from '#foo/bar/X'. How can I resolve this using #types typescript to resolve the module X and get webpack to run without errors?
My starting point was this introduction on how to how to use react and webpack with typescript: https://www.typescriptlang.org/docs/handbook/react-&-webpack.html. However, said instructions do not tackle the problem that the react component I want to use has no #types. So my first step is I needed to add #types.
There was one important nuance about the scoped module #foo/bar, which was that it broke all its subcomponents into individual sub modules like #foo/bar/X, #foo/bar/Y, and #foo/bar/Z with #foo/bar itself having no functionality. As we will see that was an important nuance which made solving this a bit trickier than if I had not had to import a scoped module into my typescript.
There is a nice blog post here about how to import a vanilla javascript into typescript. Unfortunately there is a shortcoming to the proposed approach. Namely, the idea of adding "index.d.ts' to a src/#typings has two problems:
It works only for running the typescript compiler (tsc) locally. That is to say it will make tsc happy, by allowing tsc to resolve the module from your your local ".d.ts" file, but webpack will still fail with module not found.
The proposed approach didn't teach me how to deal with scoped modules which have different rules for how folders under #types are named
Whatever approach I tried, I knew I needed to have this import statement in my typescript file:
import X from '#foo/bar/X';
ReactDOM.render(
<X/>,
document.getElementById("example")
);
Somewhere, I needed to have the following in a ".d.ts" declarations file like index.d.ts, that much was obvious:
declareĀ moduleĀ '#foo/bar';
declareĀ moduleĀ '#foo/bar/X';
But running 'webpack' yielding Module not found: Error: Can't resolve '#foo/bar/X'
I decided to run the typescript compiler (tsc) with this flag to see the possible places where tsc would try to resolve the module.
tsc --traceresolution
Using the traceresolution flag I was able to see something very interesting: that the location under node_modules/#types where tsc searches was quite unexepected (and thereby where webpack searches, since webpack follows the same rules as tsc). It was expecting to find my index.d.ts file under node_modules/#types/foo__bar NOTE THE DOUBLE UNDERSCORE. That's right, for scope packages, you cannot have node_modules/#types/#foo/bar/index.d.ts. Instead you must use a single folder under #types named foo__bar with DOUBLE UNDERSCORE.
With this knowledge I created #types/foo__bar. I copied package.json from the #foo/bar module into #types/foo__bar. I cleaned out all the scripts and other useless stuff that the #types would not need, and stripped it down to this:
{
"name": "#types/#sfoo/bar",
"version": "2.6.0",
"peerDependencies": {
"react": "^16.3",
"react-dom": "^16",
"styled-components": "^3"
},
"dependencies": {
...
},
"engines": {
"node": ">=6"
},
"gitHead": "ac0288aaa47a4f15e56db3a5eff4424fb7905419",
"main": "",
"types": "index"
}
But yet there was one more problem! Even after tsc could resolve my #types, webpack still yielded module not found: can't resolve #foo/bar. So why the heck can't webpack find it? Again, I found a flag that could show me more:
webpack --verbose
But here I had less luck since the webpack rules were just like the typescript rules for module resolution. However from the --verbose output I did notice that one file webpack was interested in was node_modules/#foo/bar/index.js. However, the bar module lacked any index.js since it was really just an empty enclosing module around submodules like #foo/bar/X. Whether this is a bug or a feature of webpack, I don't know, but ADDING AN EMPTY index.js to node_modules/#foo/bar pacified webpack, and my simple example now worked with component X displayed in the browser when I loaded the HTML page.

How do you import a "subdependency" in ES6?

I have a package react-router, which depends on path-to-regexp. react-router does not export its own import of path-to-regexp. In my top-level module, how do I import the exact same path-to-regexp that react-router uses? Or is this not possible?
For reference, I'm using Yarn as my dependency manager, and I'm considering using its resolution configuration for this purpose, but I think version mismatches could become an issue down the line.
If I could import path from 'react-router/node_modules/path-to-regexp', I would, but that doesn't seem to work. If I list path-to-regexp as a dependency of my top level module, I could still get version mismatches down the line. Maybe there's a way to use node-semver globs to reference the same version as react-router in package.json?
I believe using the resolutions feature of yarn is the best option. I can't reuse exactly the same module, but I can have a duplicate of exactly the same version in my module. And if there is a version mismatch, yarn will let me know with a warning, as described in this RFC. In other words, my package.json looks like this...
"dependencies": {
"react-router": "^4.2.0",
"path-to-regexp": "^1.7.0" <-- same version used by react-router#4.2.0
},
"resolutions": {
"path-to-regexp": "^1.7.0"
}

SyntaxError with Jest and React importing SCSS files

I am testing using Jest and my appication is running on Next.js... I am trying to test a page component in my Next application, but I am receiving errors that are shown in the following screenshot; The "Before" image is before I tried implementing a solution found on Stackoverflow, and the "After" is after the solution was implemented. I am still stuck and need some friendly help!
Here is also my current Jest config in my package.json
"jest": {
"setupFiles": ["./shim.js", "./setupTests.js"],
"verbose": true,
"moduleNameMapper": {
"^.+\\.(css|scss)$": "./cssStub.js"
}
}
Thanks!
I'm using CSS modules and it convenient for me to use "proxy" as if the code requires styles, jest will return a proxy, that will return the required field name instead of the value.
For example:
import * as styles from './styles.scss';
console.log(styles.someClassName);
// the proxy in that case will return a string with `someClassName` value.
All you need to configure is install
npm install --save-dev identity-obj-proxy
and add
"moduleNameMapper": {
"\\.(css|scss)$": "identity-obj-proxy",
}
to your Jest section in the package.json file.
Edit
Pay attention that according to the docs you should use <rootDir>
when you are mapping to a file.
"\\.(css|scss)$": "<rootDir>/cssStub.js.js",
My issue was silly enough that I wrongly specified my <rootDir> path. I would suggest reading the solution from this post for further details to how to resolve similar issue... Thanks all for the help!
SyntaxError with Jest and React and importing CSS files

Require Modernizr with Webpack

Trying to use WebPack inside grunt to get all my javascript, css and other stuff build and put in a proper places. Experiencing the following problem while using require('modernizer') inside one of my javascript files that is included in one of modules in my Gruntfile.js. The error is the following:
Fatal error: EMFILE, too many open files ../about/node_modules/modernizr/node_modules/file/lib/file.js'
When I use ulimit to increase the number of files to work with, other errors appear. In my package.json i have the following:
"dependencies": {
"jquery": "^2.1.1",
"jquery-ui": "^1.10.5",
"modernizr": "^2.8.3"
}
Is there a way to use Modernizer from pack to include it modules without using this directive on page:
<script type="text/javascript" src="{portal:createUrl('/_public/about/js/modernizr/modernizr.custom.flexbox.js')}"></script>
?
Thanks in advance!
First of all, just flagging that you should call require('modernizr') instead of require('modernizer').
Secondly, to answer your question ā€œIs there a way to use Modernizer from pack to include it modules without using this directive on page?
Yes there is. It's the script-loader. It basically allows you to require a library, and execute it as if it were inside a <script> tag. You'd use it by calling:
UPDATE 2017-12-27
require('script-loader');
require('script-loader!modernizr');
PREVIOUSLY
require('script-loader');
require('script!modernizr');
Remember to install script-loader in advance, by calling npm install script-loader --save in your command line.

Categories

Resources