First the code, it's a pretty silly example but it's pulled out from a more complicated github action:
require('@octokit/rest');
console.log('hello world');
const path = require('path');
module.exports = {
target: 'node',
entry: './index.js',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
},
};
{
"private": true,
"devDependencies": {
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10"
},
"dependencies": {
"@octokit/rest": "^16.35.0"
}
}
node_modules/.bin/webpack --config webpack.config.js
$ node index.js
hello world
$ node dist/index.js
/tmp/x/dist/index.js:1
...
ReferenceError: navigator is not defined
at Module.i (/tmp/x/dist/index.js:1:3659)
at Object.<anonymous> (/tmp/x/dist/index.js:15:6701)
at t (/tmp/x/dist/index.js:1:110)
at Object.<anonymous> (/tmp/x/dist/index.js:15:874)
at t (/tmp/x/dist/index.js:1:110)
at Object.<anonymous> (/tmp/x/dist/index.js:15:697)
at t (/tmp/x/dist/index.js:1:110)
at Object.<anonymous> (/tmp/x/dist/index.js:1:3891)
at t (/tmp/x/dist/index.js:1:110)
at Object.<anonymous> (/tmp/x/dist/index.js:15:418)
From what I've found, there's a compiled typescript package inside node_modules
that's being imported and run here, here's some of the relevant code from the last two frames:
// ...
import { getUserAgent } from "universal-user-agent";
// ...
const userAgent = `octokit-endpoint.js/${VERSION} ${getUserAgent()}`;
// ...
The universal-user-agent
provides several implementations of its code in the following files:
As you would expect, the dist-web
implementation uses navigator.userAgent
-- the node
one does something else.
I don't actually care about the user agent so I'm currently hacking around this with:
sed -i 's/\bnavigator\b/({})/g' dist/index.js
yes, running sed
to eliminate accesses to navigator
How do I convince webpack to pick the dist-node
implementation over the dist-web
one (like require(...)
seems to do when running node
directly)?
Webpack provieds a Command Line Interface (CLI), which we can call as webpack filename. js target/index. js from the terminal; and Node. js API, which we can use in our Node.
Webpack supports the following module types natively: ECMAScript modules. CommonJS modules.
This is according to their documentation: "libraryTarget: "umd" - This exposes your library under all the module definitions, allowing it to work with CommonJS, AMD and as global variable." Also, I built the exact same code with Webpack 3 and it produced a proper bundle.
When webpack processes your application, it internally builds a dependency graph from one or more entry points and then combines every module your project needs into one or more bundles, which are static assets to serve your content from.
It's a known issue for @octokit/rest: https://github.com/octokit/rest.js/issues/1485
There is also a long discussion in this universal-user-agent issue: https://github.com/gr2m/universal-user-agent/issues/23
There seems to be a permanent fix, but not released yet. Until then you can try 2 things to resolve the dist-node
of universal-user-agent
using Webpack Resolve:
alias
to resolve the dist-node
const path = require('path');
module.exports = {
target: 'node',
resolve: {
alias: {
'universal-user-agent': path.resolve(__dirname, 'node_modules/universal-user-agent/dist-node/index.js')
}
},
entry: './index.js',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
},
};
mainFields
module.exports = {
target: 'node',
resolve: {
mainFields: ['main', 'module']
},
entry: './index.js',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
},
};
You should go with the first method, because the second one reflects to all node_modules
and you'll run into issues sooner or later.
There seems to be an issue and a long discussion about this problem here: https://github.com/webpack/webpack/issues/5756
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With