evanw / esbuild

An extremely fast bundler for the web
https://esbuild.github.io/
MIT License
38.19k stars 1.15k forks source link

Timeout with codesplitting #2637

Closed scarroll32 closed 2 years ago

scarroll32 commented 2 years ago

Using esbuild with a Rails 7 app, I've been successful in code splitting 2 packages: one with the StimulusJS controllers and another with a ReactJS app. The configuration works fine in development.

When pushed to the CI (GitHub Actions) or pushed directly to Heroku, it times out.

package.json
  "scripts": {
    "build": "node app/assets/config/esbuild.js",
    "build:css": "sass ./app/assets/stylesheets/application.sass.scss ./app/assets/builds/application.css --no-source-map --load-path=node_modules"
  }
app/assets/config/esbuild.js
const path = require('path');

require("esbuild").build({
  entryPoints: ["stimulus.js","article.js"],
  bundle: true,
  minify: true,
  outdir: path.join(process.cwd(), "app/assets/builds"),
  absWorkingDir: path.join(process.cwd(), "app/javascript"),
  watch: true,
  loader: { '.js': 'jsx' },
  publicPath: 'assets',
  target: 'es6',
  // custom plugins will be inserted is this array
  plugins: [],
}).catch(() => process.exit(1));

GitHub Actions

yarn install v1.22.19
[1/4] Resolving packages...
success Already up-to-date.
Done in 0.13s.
yarn run v1.22.19
$ node app/assets/config/esbuild.js
Error: The operation was canceled.

Heroku

Hangs on this step

remote:        $ node app/assets/config/esbuild.js

Also asked here https://stackoverflow.com/questions/74217342/esbuild-timeout-with-codesplitting

hyrious commented 2 years ago

I guess you have to disable the watch option.

scarroll32 commented 2 years ago

@hyrious thank you so much, that did it:

remote:        $ node app/assets/config/esbuild.js
remote:        Done in 0.37s.

Not really sure how to have it enabled during development without updating app/assets/config/esbuild.js each time. Closing this, as it deployed.

  watch: false,  // set to true in dev
evanw commented 2 years ago

Not really sure how to have it enabled during development without updating app/assets/config/esbuild.js each time.

You can use environment variables for this. For example watch: process.env.NODE_ENV !== 'production'.

scarroll32 commented 2 years ago

That is really helpful, thank you @evanw

I discovered it is possible to console.log in esbuild.js. For anyone else who is having this problem, here is my updated script.

const path = require('path');

console.log("NODE_ENV: " + process.env.NODE_ENV);
console.log("CI: " + process.env.CI);
console.log(!(process.env.NODE_ENV === 'production' || process.env.CI));

require("esbuild").build({
  entryPoints: ["stimulus.js","article.js"],
  bundle: true,
  minify: true,
  outdir: path.join(process.cwd(), "app/assets/builds"),
  absWorkingDir: path.join(process.cwd(), "app/javascript"),
  watch: !(process.env.NODE_ENV === 'production' || process.env.CI),
  loader: { '.js': 'jsx' },
  publicPath: 'assets',
  target: 'es6',
  // custom plugins will be inserted is this array
  plugins: [],
}).catch(() => process.exit(1));
TB-Development commented 1 year ago

That is really helpful, thank you @evanw

I discovered it is possible to console.log in esbuild.js. For anyone else who is having this problem, here is my updated script.

const path = require('path');

console.log("NODE_ENV: " + process.env.NODE_ENV);
console.log("CI: " + process.env.CI);
console.log(!(process.env.NODE_ENV === 'production' || process.env.CI));

require("esbuild").build({
  entryPoints: ["stimulus.js","article.js"],
  bundle: true,
  minify: true,
  outdir: path.join(process.cwd(), "app/assets/builds"),
  absWorkingDir: path.join(process.cwd(), "app/javascript"),
  watch: !(process.env.NODE_ENV === 'production' || process.env.CI),
  loader: { '.js': 'jsx' },
  publicPath: 'assets',
  target: 'es6',
  // custom plugins will be inserted is this array
  plugins: [],
}).catch(() => process.exit(1));

I'm unable to see the output for this. I get no confirmation or error when something is broken within the build. So In fact, nothing is being "watched". I seemed to have fixed that by adding this to watch:

 watch: {
    onRebuild(error, result) {
      if (error) console.error('watch build failed:', error)
      else console.error('watch build succeeded:', result)
    },
  },

This gives me a live response in the terminal for success as:

21:15:00 js.1   | watch build succeeded: { errors: [], warnings: [], stop: [Function: stop] }

and for failure of code console.log("somethin1g" as:

21:15:40 js.1   | ✘ [ERROR] Expected ")" but found "function"
21:15:40 js.1   |
21:15:40 js.1   | watch build failed: Error: Build failed with 1 error:
21:15:40 js.1   | application.js:51:0: ERROR: Expected ")" but found "function"
21:15:40 js.1   |   errors: [
21:15:40 js.1   |     {
21:15:40 js.1   |       detail: undefined,
21:15:40 js.1   |       id: '',
21:15:40 js.1   |       location: [Object],
21:15:40 js.1   |       notes: [],
21:15:40 js.1   |       pluginName: '',
21:15:40 js.1   |       text: 'Expected ")" but found "function"'
21:15:40 js.1   |     }
21:15:40 js.1   |   ],
21:15:40 js.1   |   warnings: []
21:15:40 js.1   | }

Sourced from: https://github.com/evanw/esbuild/issues/805#issuecomment-778823204

package.json

{
  "name": "myapp",
  "private": "true",
  "scripts": {
    "build": "node esbuild.config.js"
  },
  "dependencies": {
    "@hotwired/stimulus": "^3.2.1",
    "@hotwired/turbo-rails": "^7.3.0",
    "bootstrap": "^5.2.3",
    "esbuild": "^0.16.17",
    "esbuild-rails": "^1.0.4",
    "jquery": "^3.7.0"
  },
  "devDependencies": {
    "coffeescript": "^2.7.0",
    "esbuild-coffeescript": "^2.2.0"
  }
}

entire esbuild.config.js

const path = require('path');
const rails = require('esbuild-rails')

require("esbuild").build({
  entryPoints: ["application.js"],
  bundle: true,
  minify: true,
  outdir: path.join(process.cwd(), "app/assets/builds"),
  absWorkingDir: path.join(process.cwd(), "app/javascript"),
  watch: {
    onRebuild(error, result) {
      if (error) console.error('watch build failed:', error)
      else console.error('watch build succeeded:', result)
    },
  },
  write: true,
  loader: { '.js': 'jsx' },
  publicPath: 'assets',
  target: 'es6',
  // custom plugins will be inserted is this array
  plugins: [rails()],
}).catch(() => process.exit(1));
evanw commented 1 year ago

I'm unable to see the output for this.

You may be interested in this setting: https://esbuild.github.io/api/#log-level. Specifically logLevel: 'info' enables logging at the info level.