menu

ZEIT

Our mission is to make cloud computing as easy and accessible as mobile computing. You can find our Next.js community here.

Channels
Team

Transpiling for es6 modules and node-server?

March 10, 2019 at 10:17am

Transpiling for es6 modules and node-server?

March 10, 2019 at 10:17am

How would I accomplish the above? node 8 (which is used in the node-server builder and node builder) doesn't support es6 modules (import/export). So if I want to use them, I need to transpile. I can do it using static-builder, but then the output isn't usable in the node-server builder, since anything in dist is not in source, i.e. not yet available when the node-server builder runs.

Basic layout is:

  • lib/ - all source, in es6
  • bin/now.js - single file with CJS modules for easy entrypoint

Attempt 1 - transpiled output

now.json:

"builds": [
{ "src": "package.json", "use": "@now/static-build" },
{ "src": "bin/now.js", "use": "@now/node-server" },
],
"routes": [
{ "src": "/(.*)", "dest": "/bin/now.js" }
],

and requires in /bin/now.js using the results of the static-build output, i.e. my transpilation:

const somefile = require('./../somefile')

This fails build. At build time, ./../somefile does not exist yet, since the builders are parallel.

2019-03-10T10:03:58.564Z Error: Hash: 9080f79887f0a1a954c7
Version: webpack 5.0.0-alpha.0
Time: 138ms
Built at: 2019-03-10 10:03:58
Asset Size Chunks Chunk Names
index.js 1.83 KiB {404} main
Entrypoint main = index.js
[660] /tmp/ae78388/user/bin/now.js 322 bytes {404} [built]
ERROR in /tmp/ae78388/user/bin/now.js 2:12-31
Module not found: Error: Can't resolve './../somefile' in '/tmp/ae78388/user/bin'

Attempt 2 - include existing files

Use the existing file:

now.json:

"builds": [
{ "src": "package.json", "use": "@now/static-build" },
{ "src": "bin/now.js", "use": "@now/node-server" },
],
"routes": [
{ "src": "/(.*)", "dest": "/bin/now.js" }
],

and bin/now.js:

const somefile = require('./../lib/somefile')

At least it builds, but it fails to serve:

Error while initializing entrypoint: { Error: ENOENT: no such file or directory, scandir '/var/task/user/bin/types'
at Object.fs.readdirSync (fs.js:904:18)
at Object.<anonymous> (/var/task/user/bin/now.js:10525:4)
at __webpack_require__ (/var/task/user/bin/now.js:22:30)
at Module.<anonymous> (/var/task/user/bin/now.js:30033:19)
at __webpack_require__ (/var/task/user/bin/now.js:22:30)
at Object.<anonymous> (/var/task/user/bin/now.js:31007:17)
at __webpack_require__ (/var/task/user/bin/now.js:22:30)
at module.exports.has (/var/task/user/bin/now.js:37:18)
at Object.<anonymous> (/var/task/user/bin/now.js:40:10)
at Module._compile (module.js:652:30)
errno: -2,
code: 'ENOENT',
syscall: 'scandir',
path: '/var/task/user/bin/types' }

It isn't too surprising, since the Output doesn't show those lib/ files. On the other hand, as now uses ncc and Webpack, maybe it shouldn't care?

Attempt 3 - tell node-server about all js files

Try telling node-server to handle all *.js with node-server.

now.json:

"builds": [
{ "src": "package.json", "use": "@now/static-build" },
{ "src": "bin/now.js", "use": "@now/node-server" },
{ "src": "lib/*.js", "use": "@now/node-server" }
],
"routes": [
{ "src": "/(.*)", "dest": "/bin/now.js" }
],

and bin/now.js unchanged from before:

const somefile = require('./../lib/somefile')

No difference from attempt 2 though.

Error while initializing entrypoint: { Error: ENOENT: no such file or directory, scandir '/var/task/user/bin/types'
at Object.fs.readdirSync (fs.js:904:18)
at Object.<anonymous> (/var/task/user/bin/now.js:10525:4)
at __webpack_require__ (/var/task/user/bin/now.js:22:30)
at Module.<anonymous> (/var/task/user/bin/now.js:30033:19)
at __webpack_require__ (/var/task/user/bin/now.js:22:30)
at Object.<anonymous> (/var/task/user/bin/now.js:31007:17)
at __webpack_require__ (/var/task/user/bin/now.js:22:30)
at module.exports.has (/var/task/user/bin/now.js:37:18)
at Object.<anonymous> (/var/task/user/bin/now.js:40:10)
at Module._compile (module.js:652:30)
errno: -2,
code: 'ENOENT',
syscall: 'scandir',
path: '/var/task/user/bin/types' }

What is the right way to deploy a node/node-server lambda that requires transpilation of at least some of its code?

Thanks.


March 14, 2019 at 3:15am

Still trying to figure this out. Do I need to tell the transpiler to output it to lib/ so the paths exist? Nice to see a canonical working example of it.

  • reply
  • like

March 24, 2019 at 5:53pm

You can insert a "now-build" script to make operations for you! Your now.json is really confusing, since mixing @now/static-build and @now/node(...) creates completely different outputs. Is your code public?

  • reply
  • like

Basically, with @now/node now.sh will do this: 1- Build. 2- Deploy. To customize the first one you can insert a "now-build" and manipulate things.

  • reply
  • like

Hi @paulogdm , thanks for responding (much appreciated). When you say now-build, I assume you mean in the package.json? That is what the static-build is there for, to cause gulp to run, which transpiles, generating es5 files in dist/.

  • reply
  • like

Let me turn this around? How would you build something that requires transpiling (typescript or es6 or whatever) that will be run by node-server?

  • reply
  • like

@now/node also runs now-build! Each build is completely isolated and parallel with each other, so it does not make sense to have the output of one in another...

  • reply
  • like

So just eliminate the static-build line?

  • reply
  • like

Yes, but you also need to carefully check your build process.

  • reply
  • like

Hmm, so do I need to tell node-server about all my lib/*js? Or can I rely on the fact that node-server runs it to generate dist/ output (see attempt 3 above)?

  • reply
  • like

I really am quite confused by all of it. I have all of my es6 files in lib/, es5 entrypoint in bin/now.js which includes the files from where they will be post-transpile, just unsure how to make it work.

  • reply
  • like

Can you tell me a little bit about your app? Is it express? If you do node-server on lib/*.js it will take each file and make it a independent lambda. Is that what you want?

  • reply
  • like

Not really. It is a single app, with a single entrypoint, more like a traditional now v1 app

  • reply
  • like

I really want all requests to go to one entrypoint (bin/now.js, although I can change it), and that includes various other things

  • reply
  • like

Yes, express app

  • reply
  • like

So, you may just need to do this:

"builds": [{ "src": "index.js", "use": "@now/node-server" }],
"routes": [{ "src": "/.*", "dest": "index.js" }]

Again, take a look at oure examples: https://github.com/zeit/now-examples/tree/master/express Also, be careful with that monolitich approach with lambdas, since it is not a good idea to have a BIG lambda serving all your routes! Code-splitting is the best way to have Now 2.0 in an efficient way: https://zeit.co/blog/customizable-lambda-sizes

  • reply
  • like

In that example, what is index.js? Just the equivalent of my existing bin/now.js entrypoint?

  • reply
  • like
it is not a good idea to have a BIG lambda serving all your routes!
  • reply
  • like

Of course. But there is zero chance this app will get refactored anytime in the near future. If you say, "this just isn't the way for now v2," that is fine, it just means this app isn't a good fit. Happens.

  • reply
  • like

But I did get the sense that the node and node-server were explicitly attempting to address the "not everything will be converted now" situation.

  • reply
  • like
take a look at oure examples
  • reply
  • like

That example is different in 2 key ways:

  • reply
  • like
  1. No transpiling needed, it already is es5.
  2. It serves each one as a lambda, not as modules for a single entrypoint.
Edited
  • reply
  • like

March 25, 2019 at 8:03am

@paulogdm , I tried your suggestion of using just node-server. You are right, it did, indeed, invoke npm run now-build (based on the logs), but none of the dist/ output actually shows up in the Output section; all that is there is bin/now.js, which means all of the require() fail.

  • reply
  • like

I'm trying to do the same kind of thing and running into similar issues.

My package.json looks like this

"scripts": {
"now-build": "babel src --out-dir dist",
"now-start": "node dist",
"dev": "nodemon -w src --exec \"babel-node src/index.js\"",
}

And my now.json like this

{
"version": 2,
"name": "api",
"builds": [
{
"src": "package.json",
"use": "@now/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "/dist/index.js"
}
]
}

But it doesn't seem to be building anything. Works fine when running the scripts manually on my local.

Edited
  • reply
  • like
Show more messages