Open AviVahl opened 4 years ago
Hi,
Same thing here, when typescript is bundled with create-react-app (typescript is behind ts-morph), I have 3 warnings:
./node_modules/typescript/lib/typescript.js
Critical dependency: the request of a dependency is an expression
./node_modules/typescript/lib/typescript.js
Critical dependency: the request of a dependency is an expression
./node_modules/typescript/lib/typescript.js
Module not found: Can't resolve 'perf_hooks' in 'C:\Users\User\perso\app\nocode-front\node_modules\typescript\lib'
It seems to work on a sample code, although I can't say whether all features are here.
It can be reproduced by creating a react app (e.g. npx create-react-app my-app --template typescript
) then adding the following in any of the files (e.g. index.tsx or App.tsx):
import typescript from "typescript";
console.log(typeof typescript !== 'undefined'); // To force including typescript in the bundle
Side note: when I try on codesandbox, no warning. On stackblitz, it complains that "perf_hooks" module is not found and it's blocking the bundling (installing "perf_hooks" in the dependencies doesn't solve it).
@RyanCavanaugh I am also interested in this. Do you think I should create a Pull Request with the suggested fix?
I ran into a similar issue, and worked around it by just removing the dynamic require()
s from node_modules/typescript/lib/typescript.js
at build time using string-replace-loader: https://github.com/foxglove/studio/pull/546
A cleaner workaround which we've been using for a while now (several typescript versions) is to tell webpack to avoid parsing typescript.js
:
/** @type {import('webpack').Configuration} */
module.exports = {
// ...
module: {
rules: [
// ...
],
noParse: [require.resolve('typescript/lib/typescript.js')],
},
// ...
};
Works with both webpack@4
and webpack@5
.
The above configuration (which uses require.resolve
) assumes there's a single copy of typescript being bundled, and it's the same one available to the webpack.config.js
file itself.
Angular V. 9
I had the same issue, however it was caused for this code import {toTitleCase} from "codelyzer/util/utils";
For some reason that caused the error, so I just removed it from the file where I was doing the import and the project compiled without any errors/warnings.
Just in case anybody else had the same problem.
I've tried @AviVahl 's recommended solution but it doesn't seem to do anything. In my case I'm using react-app-rewired
with the following:
config-overrides.js
const webpack = require('webpack');
module.exports = function override(config, env) {
// ....
config.plugins.push(
new webpack.ProvidePlugin({
process: 'process/browser',
Buffer: ['buffer', 'Buffer'],
}),
);
config.module.noParse = [require.resolve('typescript/lib/typescript.js')];
return config;
}
I still get the following error on build and haven't found a working solution yet, maybe I'm doing something wrong.
Module not found: Error: Can't resolve 'perf_hooks' in 'node_modules\typescript\lib'
Critical dependency: the request of a dependency is an expression
@replaysMike according to https://github.com/timarney/react-app-rewired#1-webpack-configuration---development--production
It is also not able to be used to customise the Webpack Dev Server that is used to serve pages in development mode because create-react-app generates a separate Webpack configuration for use with the dev server using different functions and defaults.
EDIT: oh, you wrote "on build", so it might be something else. Needless to say, we're still using the workaround on my team and everything works. Though our webpack config is not abstracted away by some third-party...
@AviVahl ty. That's why I was using react-app-rewired
in order to customize webpack 5 via config-overrides.js
. I don't know if this is recommended, but I was able to solve it just now with:
// config-overrides.js
module.exports = function override(config, env) {
// ...
config.module.noParse = /typescript/;
config.ignoreWarnings = [/Failed to parse source map/];
}
It seems webpack noParse ignored the path as a string and required an expression - perhaps this is a new change with webpack 5?
We're using it with webpack5. Perhaps you're on windows and experiencing C: vs c:? If launching from vscode, it messes up the drive letter (forces it to be lowercased)
hmm that's a possibility. require.resolve()
was resolving it to: B:\\gitrepo\\personalcode\\Binner\\Binner\\Binner.Web\\ClientApp\\node_modules\\typescript\\lib\\typescript.js
and the error was showing "Can't resolve 'perf_hooks' in":
B:\gitrepo\personalcode\Binner\Binner\Binner.Web\ClientApp\node_modules\typescript\lib
Perhaps internally it's not doing the comparison using double slashes?
require.resolve
returns absolute paths, so on Windows it uses just a single slash as separator. If anything stringifies that absolute path, the separators will show up as escaped slash (double slash). Perhaps react-rewired is doing something to that string when merging configs?
Another possibility is that you've inspected two different contexts: one while debugging and seeing the slash as escaped, and another seeing a printed error by webpack, where the slash will show as single.
To better understand what's going wrong, I'd pass a function to noParse
and compare the paths that come in to the result of require.resolve
: https://webpack.js.org/configuration/module/#modulenoparse
Add the following somewhere in the webpack config:
console.log(require.resolve("typescript/lib/typescript.js"));
and:
noParse: content => {console.log(content); return false;}
Because it's Windows, I'd bet it has to do with case insensitivity of paths.
To add to this, I tried the solution described in https://github.com/microsoft/TypeScript/issues/39436#issuecomment-817029140, and while it did make the warnings go away, it also completely squashed all output coming from webpack.
I.e. I no longer saw messages like
Version: webpack 4.46.0
Time: 91795ms
Built at: 07/28/2022 2:54:31 PM
Asset Size Chunks Chunk Names
0.js 702 KiB 0 [emitted] [big]
1.js 321 KiB 1 [emitted] [big]
10.js 6.09 KiB 10 [emitted]
and instead just
webpack built 87d9467409f36894a95e in 91766ms
Hopefully this gets fixed internally to TypeScript.
I have the same issue in recent create-react-app, unfortunately any of the above doesn't work. I use react-app-rewired, webpack 5 and config-overrides.js
Any chance we can introduce the suggestion from @AviVahl ?
@replaysMike 's solution works for me in current webpack/ts/etc versions!
I am trying to compile typescript code in the browser and stumble upon this problem. It works in a simple isolated test case I wrote works, but when I move it to a larger production code it fails because of this "can't resolve 'perf_hooks'" error, and adding the noParse rule does not solve it (it rather moves the error from the bundle time to the run time). What is the solution? My current solution is to load the package from A CDN and that works... But I'd rather resolve it at the bundlign time. https://github.com/croquet/microverse/blob/ac3a5412ad6b4ec860e209bec9836fd9f33cf2e8/prelude.js#L63
Didn't realize this issue existed; one thing you may try is to just use an IgnorePlugin
to bulk ignore all require
calls; if you're bundling for the browser they won't be used anyway.
I have not tested, but something like:
new webpack.IgnorePlugin({
resourceRegExp: /.*/,
contextRegExp: /typescript.js$/,
});
Though if you have an easy repro I'd be happy to play around with it.
Thanks for a reply. This IgnorePlugin does not work for me (I tried some different RegExps). Yes, I'll try to make a smaller repro... but that has been hard. I can make a branch on the above microverse repo that changes the script line with import to test it, if you are willing to try it in that form.
Didn't realize this issue existed; one thing you may try is to just use an
IgnorePlugin
to bulk ignore allrequire
calls; if you're bundling for the browser they won't be used anyway.I have not tested, but something like:
new webpack.IgnorePlugin({ resourceRegExp: /.*/, contextRegExp: /typescript.js$/, });
Though if you have an easy repro I'd be happy to play around with it.
This branch, which is not an isolated test case though, shows the issue: https://github.com/croquet/microverse/tree/ts-import-test
@yoshikiohshima I finally had time to look at the above; the issue here comes down to the fact that our package.json
doesn't include perf_hooks
in the browser
section of package.json
, which was unintentional. I've sent #56062 for that.
thanks!
FWIW there's a similar warning that occurs when bundling for the browser using Vite. It looks like this:
> vite build
vite v4.5.0 building for production...
[plugin:vite:resolve] Module "perf_hooks" has been externalized for browser compatibility, imported by
"/home/curran/repos/vzcode/node_modules/typescript/lib/typescript.js". See
http://vitejs.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility
for more details.
Fingers crossed that the changes in https://github.com/microsoft/TypeScript/pull/56062 solve this issue as well! Thank you for the fix.
It definitely should; you can try out the RC or nightly.
TypeScript Version: 3.9.6 and 4.0.0-dev.20200706
Search Terms: webpack request of a dependency expression
Code
Expected behavior: Bundle successfully, and without warnings, using webpack.
Actual behavior: Bundles successfully, but a warning is shown:
Playground Link: N/A
Related Issues: Couldn't find any that talked about this issue
Suggested fix:
The warning is printed due to the following dynamic require call:
Rather than calling require directly, create a helper function:
And call it the following way:
The resulting code will behave 1:1 in Node, while not triggering any warnings in bundlers trying to resolve these dynamic calls.