web-dev-qa-db-fra.com

Comment utiliser WebPack avec un monorepo (espaces de travail yarnpkg)

J'utilise yarn workspaces où le répertoire racine contient un répertoire de packages contenant tous mes dépôts. Chaque dépôt a son propre répertoire node_modules contenant ses dépendances. Le répertoire racine node_modules contient toutes les dépendances de développement pour l'ensemble du projet, ainsi que tous les autres éléments liés aux développeurs, tels que les fichiers webpack.config. Webpack utilise le rechargement de module à chaud pour le package de serveur express.

Le problème que j'ai est, comment configurer externes Webpack pour exclure tous les répertoires node_modules à travers le projet entier, pas seulement à la racine?

webpack-node-externals ne semble pas fonctionner dans ce scénario.

Message d'erreur: 

WARNING in ./packages/servers/express/node_modules/colors/lib/colors.js
127:29-43 Critical dependency: the request of a dependency is an expression

WARNING in ./packages/servers/express/node_modules/express/lib/view.js
79:29-41 Critical dependency: the request of a dependency is an expression

Configuration Webpack: 

const webpack = require('webpack');
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const StartServerPlugin = require('start-server-webpack-plugin');

module.exports = {
  entry: [
    'babel-polyfill',
    'webpack/hot/poll?1000',
    path.join(__dirname, '../packages/servers/express/server/index.js')
  ],
  watch: true,
  target: 'node',
  externals: [
    nodeExternals({
      whitelist: ['webpack/hot/poll?1000']
    })
  ],
  resolve: {
    alias: {
      handlebars: 'handlebars/dist/handlebars.js'
    }
  },
  module: {
    rules: [
      {
        test: /\.js?$/,
        use: 'babel-loader',
        exclude: /node_modules/
      }
    ]
  },
  plugins: [
    new StartServerPlugin('server.js'),
    new webpack.NamedModulesPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.DefinePlugin({
      'process.env': { BUILD_TARGET: JSON.stringify('server') }
    })
  ],
  output: {
    path: path.join(__dirname, '../packages/servers/express/.build'),
    filename: 'server.js'
  }
};
11
otissv

Grâce à @blackxored, j'ai pu résoudre ce problème dans mon projet.

Dans votre fichier de configuration webpack, procédez comme suit:

import nodeExternals from 'webpack-node-externals'

Puis ajouter

externals: [
  nodeExternals({
    modulesFromFile: true,
  }),
],
4

Les espaces de travail en fil jettent des modules compatibles dans le répertoire noeud_modules racine, laissant ainsi tous les modules incompatibles (différents semver, etc.) avec le répertoire node_modules de l'espace de travail dépendant. Si un package est demandé sans utiliser de chemin relatif, il est soit natif, issu de node_module, soit éventuellement d'un package lié par un lien symbolique à partir de l'un de vos espaces de travail. Vous voulez probablement que tous ces paquets soient externes.

comment configurer les composants externes de WebPack pour exclure tous les répertoires node_modules du projet entier, et pas seulement de la racine?

Je voudrais essayer en utilisant une fonction avec l'option externe de Webpack . Vous recevez le contexte du paramètre require, le nom du module demandé et un rappel pour indiquer si cette importation particulière (require) doit être considérée comme externe.

externals: [
    (ctx, req, cb) => {
        if (!/node_modules/.test(ctx) && req[0] !== '.') {
            // Assumes you have defined an "entries" variable
            let notAnEntry = (path) => {
                return Object.keys(entries).every((entry) => {
                    return entries[entry] !== path
                });
            };

            if (notAnEntry(require.resolve(req))) {
                // This module is external in a commonjs context
                return cb(null, `commonjs ${req}`);
            }
        }

        cb();
    }
]
2
Morgan

Si vous utilisez des espaces de travail en fil avec webpack-node-externals, une meilleure solution que de définir modulesFromFile: true consiste à utiliser le paramètre externals suivant dans la configuration de votre pack Web:

externals: [
  nodeExternals(),
  nodeExternals({
    modulesDir: path.resolve(__dirname, 'path/to/root/node_modules'),
  }),
],

Utilisant essentiellement deux instances de nodeExternals. 1 pour le paquet node_modules et un pour le node_modules racine.

2
Max Parelius