How to create a module for: web, require by node *

2019-08-22 07:33发布

TLDR; What's the best way to create a module that can be bundled for web, required by a node app, and required by a node module that is being bundled for web?

I started by having two entry points, one for node (index.js) and one for web (index-web.js). This works fine for bundling for web because webpack uses index-web.js. It also works for require by a node app because it picks up index.js. So first two items 'check'.

But it doesn't work if I require my module from a node app that is being bundled for web, because it picks up index.js by default. Maybe there's a simple way to handle that?

So Q1: Is there a way for the dependent module to pick up the web entry point (index-web.js) or even the web bundle when it npm installs or npm links my module?

I have tried switching to just using index.js and putting conditional requires in there (conditional on (typeof window === 'undefined')) which kind of works, but:

A) I'm left with those annoying "Warning: Critical dependency" messages that I am about to look into (webpack issue #196).

B) I have to modify the webpack.config.js of the dependency module to exclude certain builtins (using externals) that are now referenced because I'm using conditional requires in index.js. This is a deal breaker in the long run.

1条回答
等我变得足够好
2楼-- · 2019-08-22 07:57

I found a good solution is to use a combination of the npm node-detect package and the webpack DefinePlugin. This ensures that webpack only packages modules required for web and eliminates the webpack warnings about "Critical dependency: the request of a dependency is an expression".

So in your isomorphic modules (dependent and dependency):

npm install --save detect-node

or

yarn add detect-node

In both webpack.config.js:

    const webpack = require('webpack')
    // ...
    module.exports = {
      // ...
      plugins: [
        new webpack.DefinePlugin({
          IS_BROWSER: true
        })
      ]
    }

In your code:

    const isNode = require(detect-node)
    if (isNode) {
        if (!IS_BROWSER) {
          // Ignored by webpack, handled by node
          safeJs.safeApi = require('./bootstrap')   
        }
    } else {
          // Ignored by node, handled by webpack
          window.safeJs = safeJs
          safeJs.safeApi = require('./bootstrap-web')
    }
查看更多
登录 后发表回答