nx icon indicating copy to clipboard operation
nx copied to clipboard

feat(node): allow executing esm compiled scripts

Open bulldog98 opened this issue 2 years ago • 16 comments

Current Behavior

The @nrwl/node:node executor is not able to execute esm module scripts

Expected Behavior

The @nrwl/node:node executor is able to execute esm module scripts

bulldog98 avatar May 21 '22 12:05 bulldog98

☁️ Nx Cloud Report

We didn't find any information for the current pull request with the commit e6fdb7feb45622b9a07ef63e7da3ad05a6a2be17. You might need to set the 'NX_BRANCH' environment variable in your CI pipeline.

Check the Nx Cloud Github Integration documentation for more information.


Sent with 💌 from NxCloud.

nx-cloud[bot] avatar May 21 '22 12:05 nx-cloud[bot]

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Ignored Deployment
Name Status Preview Comments Updated (UTC)
nx-dev ⬜️ Ignored (Inspect) May 4, 2023 9:45pm

vercel[bot] avatar May 21 '22 12:05 vercel[bot]

Why did the build not run?

bulldog98 avatar May 24 '22 20:05 bulldog98

@bulldog98 , thank you for the PR. Can you add some e2e tests for this change?

nartc avatar Jun 04 '22 04:06 nartc

@bulldog98 , thank you for the PR. Can you add some e2e tests for this change?

Sure I first did not see there where e2e tests, but found them now.

bulldog98 avatar Jun 04 '22 07:06 bulldog98

@nartc I was unable to run the e2e test locally, how are they executed?

bulldog98 avatar Jun 04 '22 08:06 bulldog98

@bulldog98 I've rebased the branch and kicked off the build which is failing. Can you take a look? To run test locally, you'd need to start local-registry with:

yarn local-registry enable
yarn local-registry start

then run the e2e:

yarn nx e2e e2e-node

nartc avatar Jun 09 '22 20:06 nartc

sure I'm working on fixing the test.

bulldog98 avatar Jun 10 '22 17:06 bulldog98

@nartc I fixed the e2e test it works now

bulldog98 avatar Jun 11 '22 11:06 bulldog98

I had the same problem. How can I use this pr to test if it's the same problem?

StringKe avatar Jun 13 '22 06:06 StringKe

@nartc sorry I had messed up the check to beEqual, but it should be a toContains

bulldog98 avatar Jun 20 '22 19:06 bulldog98

@bulldog98 Thanks for the PR. Everything looks good so far. Just one quick question, why did you have the following?

...
const dynamicImport = new Function('specifier', 'return import(specifier)');
...

Would this work as well?

...
function dynamicImport(specifier) {
   return import(specifier);
}

dynamicImport(fileToRun);
...

nartc avatar Jun 21 '22 13:06 nartc

That said, I'm curious why not just import(fileToRun)

luxaritas avatar Jun 21 '22 13:06 luxaritas

The problem is that typescript transpiles the import(fileToRun) to require(fileToRun) the same happens with the version of @nartc.

bulldog98 avatar Jun 21 '22 16:06 bulldog98

The "real" fix would be to change "module" to "es2020" in the tsconfig - that would be a much larger change, but also this implicitly breaks environments that don't support the dynamic import syntax natively instead of explicitly. I think all current supported node versions should though?

luxaritas avatar Jun 21 '22 16:06 luxaritas

@luxaritas yep, that's my concern as well. I also think the real fix is to support ESM across the board. With TS 4.7, we have a more "official" ESM support but we're somewhat waiting for the dust to settle before making substantial changes to all plugins.

nartc avatar Jun 21 '22 16:06 nartc

pick up config from test case

nrwl build app support esm will fix some problem. use custom webpack

project.json

{
   "targets": {
     "build": {
      "executor": "@nrwl/node:webpack",
      "outputs": ["{options.outputPath}"],
      "options": {
        "outputPath": "dist/apps/<project>",
        "main": "apps/<project>/src/main.ts",
        "tsConfig": "apps/<project>/tsconfig.app.json",
        "assets": ["apps/<project>/src/assets"],
        "webpackConfig": "apps/<project>/webpack.config.js"   <== add this
      },
  }
}

apps//webpack.config.js

module.exports = (config, context) => ({
  ...config,
  experiments: {
    ...config.experiments,
    outputModule: true,
    topLevelAwait: true,
  },
  output: {
    path: config.output.path,
    chunkFormat: 'module',
    library: {
      type: 'module',
    },
  },
})

LinboLen avatar Sep 08 '22 07:09 LinboLen

Closing because we'd like to implement a better fix across Nx to support ESM instead of dynamic import hack. Thank you bulldog98 for the PR but I'll be closing this.

nartc avatar Sep 23 '22 09:09 nartc

@nartc - This problem has completely derailed one of our active projects and it seems like many others on this thread are struggling with this also. Because of that I truly hope that closing this PR means that there will be an official fix released in the very near future.

kevinkmp avatar Sep 23 '22 15:09 kevinkmp

Created similar bug to this one https://github.com/nrwl/nx/issues/12259

@nartc that's great news! is there anywhere we can track/contribute to this?

sndrs avatar Sep 27 '22 13:09 sndrs

I hope this issue is solved soon! I've just upgraded my project to v14 and now I'm not able to do anything with it unless this issue is solved! My project is practically frozen!

omsharp avatar Oct 13 '22 22:10 omsharp

why is it so complicated, seriously, i just want to set my f*cking desk on fire. 3 hours trying to add an app to NX that only uses yargs and inquirer 😮‍💨 , i quit

try this https://github.com/esbuild-kit/tsx just run command

StringKe avatar Oct 14 '22 08:10 StringKe

as a workaround, is it possible to tell webpack to handle a specific node module as esm?

psuedo code:

// webpack.config.js
module: {
      rules: [
        {
          test: /node_modules/the-package,
          target: "module",
loader: "babel-loader",
        },
      ],
    },

goldylucks avatar Oct 15 '22 12:10 goldylucks

@nartc 15.3.0 came out today, yet this is still broken. What's up?

codeedog avatar Dec 08 '22 20:12 codeedog

I just upgraded to 15.4.2, and my project is borked. I'm not even sure there's a possible path forward until nx has ESM support... but does anyone have a workaround in the meantime?

quaelin avatar Jan 02 '23 20:01 quaelin

@quaelin you can patch the file in the error directly and replace the require with import

bulldog98 avatar Jan 02 '23 21:01 bulldog98

@quaelin

I am using the following solution to solve the esm problem, you can refer to use it.

// apps/SOME/webpack.config.cjs

const nodeExternals = require('webpack-node-externals')

module.exports = (config, context) => {
	return {
		...config,
		externalsPresets: {
			node: true,
		},
		output: {
			...config.output,
			module: true,
			libraryTarget: 'module',
			chunkFormat: 'module',
			library: {
				type: 'module',
			},
			environment: {
				module: true,
			},
		},
		experiments: {
			outputModule: true,
		},
		externals: nodeExternals({
			importType: 'module',
		}),
	}
}

// project.json or workspace.json
                    "build": {
			"executor": "@nrwl/webpack:webpack",
			"dependsOn": ["build-porto"],
			"outputs": ["{options.outputPath}"],
			"options": {
				"target": "node",
				"compiler": "tsc",
				"outputPath": "dist/apps/api",
				"main": "apps/api/src/main.ts",
				"tsConfig": "apps/api/tsconfig.app.json",
				"assets": ["apps/api/src/assets"],
                                 // add next line
				"webpackConfig": "apps/api/webpack.config.cjs",
				"generatePackageJson": true
			},

add package.json or create package.json

//apps/SOME/package.json

"type": "module"

update project tsconfig.json

// tsconfig.app.json
{
	"extends": "./tsconfig.json",
	"compilerOptions": {
		"outDir": "../../dist/out-tsc",
                 // change this
		"module": "es2020",
		"types": ["node"]
	},
	"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
	"include": ["src/**/*.ts"]
}

pnpm patch

  1. pnpm patch @nrwl/js
  2. modify src/executors/node/node-with-require-overrides.js
-require(fileToRun);
+const dynamicImport = new Function('specifier', 'return import(specifier)');
+dynamicImport(fileToRun);
  1. pnpm patch-commit [path], path from step 1

In addition to using pnpm patch you can also use https://github.com/ds300/patch-package

StringKe avatar Jan 03 '23 01:01 StringKe

@nartc @luxaritas Any plan for the official fix to be rolled out?

tuyen-vuduc avatar Jan 16 '23 22:01 tuyen-vuduc

@nartc @luxaritas Will it be much better for the community to have this workaround merged while you are doing internal fix the perfect way? I think a lot of projects have been being impacted by this...

tuyen-vuduc avatar Jan 17 '23 22:01 tuyen-vuduc