如何在 yarn 工作区的 remix-运行 应用程序中使用本地模块
How to use Local modules in remix-run application in yarn workspaces
我有一个 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-运行 github 上的问题很少,但似乎没有任何帮助。
截至 2022 年 2 月 3 日,remix-run 没有官方支持在 yarn workspaces monorepo 中构建本地包。我能够修补 esbuild 配置并允许构建本地模块。
here 是 remix 运行 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"
}
我有一个 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-运行 github 上的问题很少,但似乎没有任何帮助。
截至 2022 年 2 月 3 日,remix-run 没有官方支持在 yarn workspaces monorepo 中构建本地包。我能够修补 esbuild 配置并允许构建本地模块。 here 是 remix 运行 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"
}