当使用`target:node`时,如何说服webpack使用节点导入而不是Web导入

时间:2019-11-24 21:52:00

标签: javascript node.js webpack

首先是代码,这是一个非常愚蠢的示例,但是它是从更复杂的github操作中撤出的:

index.js

require('@octokit/rest');
console.log('hello world');

webpack.config.js

const path = require('path');

module.exports = {
  target: 'node',
  entry: './index.js',
  output: {
    filename: 'index.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

package.json

{
  "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

在没有webpack的情况下运行

$ node index.js
hello world

构建Webpack后运行

$ 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)

分析

从我发现的情况来看,node_modules中有一个已编译的打字稿包,正在导入该包并在此处运行,这是最后两帧中的一些相关代码:

node_modules/@octokit/endpoint/dist-src/defaults.js

// ...
import { getUserAgent } from "universal-user-agent";
// ...
const userAgent = `octokit-endpoint.js/${VERSION} ${getUserAgent()}`;
// ...

universal-user-agent在以下文件中提供了其代码的几种实现:

  • node_modules / universal-user-agent / dist-node / index.js
  • node_modules / universal-user-agent / dist-web / index.js

如您所料,dist-web实现使用navigator.userAgentnode实现了其他功能。


我当前的可怕解决方法

我实际上并不在乎用户代理,所以我目前正在利用以下方法

sed -i 's/\bnavigator\b/({})/g' dist/index.js

是,运行sed以消除对navigator的访问


tl; dr

我如何说服webpack在dist-node之上选择dist-web实现(就像require(...)似乎在直接运行node时那样)?

1 个答案:

答案 0 :(得分:6)

这是@octokit/rest的已知问题:https://github.com/octokit/rest.js/issues/1485

universal-user-agent问题中还有很长的讨论:https://github.com/gr2m/universal-user-agent/issues/23

似乎有一个永久修复程序,但尚未发布。在此之前,您可以尝试使用Webpack Resolve通过以下两种方法来解决dist-node中的universal-user-agent

1)使用alias来解析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'),
  },
};

2)使用mainFields

module.exports = {
  target: 'node',
  resolve: {
    mainFields: ['main', 'module']
  },
  entry: './index.js',
  output: {
    filename: 'index.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

您应该使用第一种方法,因为第二种方法可以反映所有node_modules,并且您迟早会遇到问题。

Webpack问题

这里似乎存在一个问题,并且对此问题进行了长时间的讨论:https://github.com/webpack/webpack/issues/5756