【问题标题】:How to use Local modules in remix-run application in yarn workspaces如何在纱线工作区的混音运行应用程序中使用本地模块
【发布时间】:2026-02-17 15:10:01
【问题描述】:

我有一个yarnworkspacemonorepo,其中不同的包包含可重用的代码。像 @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 上的问题很少,但似乎没有任何帮助。

【问题讨论】:

    标签: reactjs monorepo esbuild remix.run


    【解决方案1】:

    截至 2022 年 2 月 3 日,remix-run 不再提供官方支持,用于在 yarn 工作区 monorepo 中构建本地包。我能够修补 esbuild 配置并允许构建本地模块。 here 是 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"
    }
    

    【讨论】:

    • remix 不支持本地构建本地模块。