0

我有一个yarn workspace monorepo不同的包包含可重用代码的地方。像 @pkg/styles@pkg/ui-components

所有这些包都es modules (import export statements)在我的由 webpack 构建的非 ssr 应用程序中使用,就像这样。

例如

import { box } from '@pkg/styles'
import {Button} from '@pkg/ui-components'

现在我需要添加remix-run到同一个 monorepo 并且一切正常,直到我开始导入这些本地包。我得到这个错误

import box from './box';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    at Module._compile (node:internal/modules/cjs/loader:1065:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)

如果我没记错的话,这是因为esbuild期望所有内容都node_modules被预编译。并在转译阶段简单地忽略它们。

我需要告诉我的编译器在编译时考虑我的本地包,这在我们使用时非常容易做到webpack。但我不确定如何在remix-run内部使用它和 esbuild。remix-run github 上几乎没有问题,但似乎没有任何帮助。

4

1 回答 1

1

截至 2022 年 2 月 3 日,remix-run 没有官方支持在纱线工作区 monorepo 内构建本地包。我能够修补 esbuild 配置并允许构建本地模块。 是 remix run repo 上提出的官方问题。

我最终做的是修补 remix esbuild 配置

esbuild-overrides.js在项目根目录下创建

添加以下代码

const esbuild = require('esbuild');
const Module = require('module');

function manualExternalsPlugin() {
  return {
    name: 'manual-externals-overide',
    setup(build) {
      build.onResolve(
        {
          filter: /@YourNamespaceOrPackageName/,
        },
        (args) => {
          return {
            external: false,
            namespace: args.path,
          };
        },
      );
    },
  };
}

const originalRequire = Module.prototype.require;
const originalBuild = esbuild.build;

function build(options) {
  if (options.platform === 'node') {
    const { plugins } = options;
    const externalPlugin = plugins.find(
      (plugin) => plugin.name === 'manual-externals',
    );
    const localPlugins = plugins.filter(
      (plugin) => plugin.name !== 'manual-externals',
    );
    localPlugins.push(manualExternalsPlugin());
    localPlugins.push(externalPlugin);
    return originalBuild({
      ...options,
      plugins: localPlugins,
    });
  }
  return originalBuild({
    ...options,
  });
}

Module.prototype.require = function (id) {
  // when remix requires esbuild, it will get our modified build function from above
  if (id === 'esbuild') {
    return { ...esbuild, build };
  }
  return originalRequire.apply(this, arguments);
};

更新构建脚本


"scrips": {
      "dev:patched": "NODE_OPTIONS='-r ./esbuild-overrides' remix dev",
     "build:patched": "NODE_OPTIONS='-r ./esbuild-overrides' remix build"
}
于 2022-02-03T13:12:13.180 回答