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

Ant*_*ile 6 javascript node.js webpack

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

索引.js

require('@octokit/rest');
console.log('hello world');
Run Code Online (Sandbox Code Playgroud)

webpack.config.js

const path = require('path');

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

包.json

{
  "private": true,
  "devDependencies": {
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.10"
  },
  "dependencies": {
    "@octokit/rest": "^16.35.0"
  }
}
Run Code Online (Sandbox Code Playgroud)

构建命令

{
  "private": true,
  "devDependencies": {
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.10"
  },
  "dependencies": {
    "@octokit/rest": "^16.35.0"
  }
}
Run Code Online (Sandbox Code Playgroud)

不使用 webpack 运行

$ node index.js
hello world
Run Code Online (Sandbox Code Playgroud)

构建 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)
Run Code Online (Sandbox Code Playgroud)

分析

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

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

node_modules/.bin/webpack --config webpack.config.js
Run Code Online (Sandbox Code Playgroud)

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

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

正如您所期望的那样,dist-web实现使用navigator.userAgent-node一个做其他事情。


我目前糟糕的解决方法

我实际上并不关心用户代理,所以我目前正在解决这个问题

$ node index.js
hello world
Run Code Online (Sandbox Code Playgroud)

是的,运行sed以消除对navigator


tl;博士

我如何说服 webpack 选择dist-node实现而不是dist-web一个实现(就像直接require(...)运行时一样node)?

Chr*_*ras 8

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

这个通用用户代理问题也有很长的讨论:https : //github.com/gr2m/universal-user-agent/issues/23

似乎有一个永久修复,但尚未发布。在那之前,你可以尝试两件事情来解决dist-nodeuniversal-user-agent使用的WebPack解决

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'),
  },
};
Run Code Online (Sandbox Code Playgroud)

2) 使用 mainFields

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

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

网络包问题

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