Webpack разрешает псевдоним и компилирует файл под этим псевдонимом. - PullRequest
0 голосов
/ 15 апреля 2020

У меня есть проект, который использует lerna (monorepo, несколько пакетов). Немногие из пакетов являются автономными приложениями.

Чего я хочу добиться - это иметь псевдонимы в нескольких пакетах, чтобы иметь что-то вроде внедрения зависимостей. Так, например, у меня есть псевдоним @package1/backendProvider/useCheckout и в веб-пакете в моем автономном приложении я определяю его как ../../API/REST/useCheckout. Поэтому, когда я меняю бэкэнд-провайдера на что-то другое, я бы изменил его только в веб-пакете.

Проблема

Проблема возникает, когда этот псевдоним используется другим пакетом (не автономным). приложение). Например:

Структура каталогов выглядит следующим образом:

Project
    packageA
           ComponentA
    packageB
           API
              REST
                  useCheckout
    standalone app

Компонент A находится в пакете A

useCheckout находится в пакете B в /API/REST/useCheckout path

ComponentA использует useCheckout с псевдонимом, таким как import useCheckout from '@packageA/backendProvider/useCheckout

Автономное приложение использует компонентA

Я получаю ошибку, что Module not found: Can't resolve '@packageA/backendProvider/useCheckout

Однако, когда такой же псевдоним используется в автономном приложении (который имеет веб-пакет с конфигурацией, представленной ниже), он работает. Проблема возникает только для зависимостей.

Потенциальные решения

Я знаю, что одним из решений было бы скомпилировать каждый пакет с веб-пакетом, но это не кажется дружелюбным. То, что я думаю выполнимо, это сказать webpack разрешить эти псевдонимы к путям каталогов, а затем перекомпилировать его. Первая часть (разрешение псевдонимов) завершена.

Текущий код

Поскольку я использую Next JS, мой конфиг веб-пакета выглядит следующим образом:

 webpack: (config, { buildId, dev, isServer, defaultLoaders }) => {
    // Fixes npm packages that depend on `fs` module
    config.node = {
      fs: "empty"
    };

    const aliases = {
    ...
      "@package1/backendProvider": "../../API/REST/"
    };

    Object.keys(aliases).forEach(alias => {
      config.module.rules.push({
        test: /\.(js|jsx)$/,
        include: [path.resolve(__dirname, aliases[alias])],
        use: [defaultLoaders.babel]
      });

      config.resolve.alias[alias] = path.resolve(__dirname, aliases[alias]);
    });

    return config;
  }

1 Ответ

1 голос
/ 21 апреля 2020

Вам не нужно использовать псевдонимы. У меня похожая настройка, просто переключитесь на рабочие пространства yarn (v1), что делает довольно хитрый трюк, он добавляет ссылку sym на все ваши пакеты в root node_modules .

This Таким образом, каждый пакет может импортировать другие пакеты без каких-либо проблем.

Чтобы применить рабочие области пряжи с помощью lerna:

// lerna.json
{
  "npmClient": "yarn",
  "useWorkspaces": true,
  "packages": [
    "packages/**"
  ],
}
// package.json
{
  ...
  "private": true,
  "workspaces": [
    "packages/*",
  ]
  ...
}

Это позволит включить рабочую область пряжи с помощью lerna.

Единственное, что остается решить - создать потребительский пакет для переноса требуемого пакета (поскольку стандартные конфигурации babel и webpack игнорируют трансплантацию node_module).

В проекте Next. js это просто, используйте next-transpile-modules .

// next.config.js

const withTM = require('next-transpile-modules')(['somemodule', 'and-another']); // pass the modules you would like to see transpiled

module.exports = withTM();

В других пакетах, использующих веб-пакет, вам нужно будет указать веб-пакету для транспортировки ваших использованных пакетов (предположим, что они находятся под npm scope of @somescope/).

Так, например, для переноса машинописного текста вы можете добавить дополнительный загрузчик модулей.

// webpack.config.js
{
  ...
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        include: /[\\/]node_modules[\\/]@somescope[\\/]/, // <-- instruct to transpile ts files from this path
        options: {
          allowTsInNodeModules: true, // <- this a specific option of ts-loader
          transpileOnly: isDevelopment,
          compilerOptions: {
            module: 'commonjs',
            noEmit: false,
          },
        },
      }
    ]
  }
  ...
  resolve: {
      symlinks: false, // <-- important
  }
}

Если у вас есть css, вы получите N Также необходимо добавить раздел для css.

Надеюсь, это поможет.

Преимущество: рабочие пространства пряжи уменьшат размер вашего node_modules, поскольку он будет устанавливать дубликаты пакетов (с той же версией semver) один раз!

...