remix
remix copied to clipboard
Cannot use import statement outside a module (in monorepo)
What version of Remix are you using?
latest
Steps to Reproduce
https://github.com/ahoyahoy/remix-super-error
run in root
npm i
npm run dev
open http://localhost:3000 and http://localhost:3008
Expected Behavior
Next.js (port 3000) app works correctly and import Button from UI package.
I want same result in Remix app (without build UI package). Also I want to use same approach with shared tsconfig.
Actual Behavior
Remix app return error SyntaxError: Cannot use import statement outside a module
.
Also remix always rewrite my tsconfig... which is pretty annoying (https://github.com/remix-run/remix/discussions/3180)
Something definitely off.
I have a remix app in a monorepo with the version 1.6.7
and works perfectly. Upgrading to version 1.7.2
I get this problem as well
I have confirmed this is still an issue on 1.7.5
remix has major issues resolving local dependencies in mono repos, i'm not sure if its something to do with the symlinks - but i've been pulling my hair out all day trying to import a TS local library into my Remix app.
Here is another reproduction of this issue
https://github.com/dan-cooke/remix-esbuild-resolve-bug
- Run
yarn
-
yarn build --filter remix-example
- Inspect the build output
You will see that the ui
has not been bundled
var import_react2 = require("@remix-run/react"), import_ui = require("ui"), import_jsx_dev_runtime = require("react/jsx-dev-runtime"), meta = () => ({
charset: "utf-8",
title: "New Remix App",
viewport: "width=device-width,initial-scale=1"
});
And of course if you try to execute this you will get the OP error "Cannot use ipmort statement outside a module"
Because node require will try to require the TS version of the UI module.
This issue makes developing Remix in a monorepo incredibly annoying as you will have to create buildable versions of all your TS libraries and pre-build them before your remix app.
Okay I've figured it out.
After digging into the compiler code and finding what I assumed to be a buggy plugin serverBareModulesPlugin
, I discovered a hidden (not really I just haven't read the docs in a while) option in the remix config.
serverDependenciesToBundle
You can specify your local modules in here and remix will include them in the bundle.
/** @type {import('@remix-run/dev').AppConfig} */
module.exports = {
ignoredRouteFiles: ["**/.*"],
// appDirectory: "app",
// assetsBuildDirectory: "public/build",
// serverBuildPath: "build/index.js",
+ serverDependenciesToBundle: ["@baggers/ui"],
// publicPath: "/build/",
};
Brief Explanation
It appears that the serverBareModulesPlugin
is marking every module as external, unless it passes certain criteria to be bundled. Which when you think about it - makes a lot of sense. E.g most modules are external unless they start with ./
or /
Here is the line in question. https://github.com/remix-run/remix/blob/main/packages/remix-dev/compiler/plugins/serverBareModulesPlugin.ts#L123
Hope this helps someone
@ahoyahoy Can you give @dan-cooke suggestion a try and see if it fixes your issue? 🙏🏼
This issue has been automatically closed because we haven't received a response from the original author 🙈. This automation helps keep the issue tracker clean from issues that are unactionable. Please reach out if you have more information for us! 🙂