Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate Rails JS bundling #315

Merged
merged 6 commits into from
Feb 9, 2022
Merged

Integrate Rails JS bundling #315

merged 6 commits into from
Feb 9, 2022

Conversation

rosle
Copy link
Contributor

@rosle rosle commented Jan 24, 2022

#310

What happened

As Rails moving away from webpacker gem. We need to get our template up-to-date.

For applications currently using Webpacker, the first recommendation is to switch to jsbundling-rails with Webpack (or another bundler).

Insight

yarn run build will bundle our scripts to the app/assets/builds

though the script works perfectly with

"scripts": {
  "build": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds"
}

I decided to separate the build script out to app/javascript/build.js, this will allow us to customize the esbuild easier.

Typescript

For Typescript, it has built-in support from esbuid. So we don't need to do anything. After the project is created, just simply rename files to .ts and it should work. 👍

To make the template fully support Typescript (auto-generate .ts file in the first place), I'm thinking of renaming the file with the script below.

Dir.glob('app/javascript/**/*.js').each { |file| File.rename(file, file.sub('.js', '.ts')) }
gsub_file 'package.json', '.js', '.ts'

This works but I have problem on the test. It is more confused because the template is applying on .js file but in the expectation, we validate against the .ts file.

I would prefer to revisit this issue later, maybe we can just rename all files to .ts everywhere in the template in the first place but this will have effect that If we run install script from other gems, they might look for .js to modify but it doesn't exist anymore.

Proof Of Work

Site is working.

Screen Shot 2565-01-26 at 12 36 53

Tested with Typescript, it's working correctly.

Screen Shot 2565-01-26 at 12 42 44

Screen Shot 2565-01-26 at 12 43 47

@rosle rosle added this to the 5.0.0 milestone Jan 24, 2022
@rosle rosle self-assigned this Jan 24, 2022
@rosle rosle force-pushed the feature/integrate-js-bundling branch 8 times, most recently from e038af7 to f155ef1 Compare January 26, 2022 05:45
@rosle rosle requested a review from a team January 26, 2022 08:30
@rosle rosle marked this pull request as ready for review January 26, 2022 08:30
Copy link
Contributor

@olivierobert olivierobert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, this looks great. I just have one minor concern/question.


require('esbuild').build({
entryPoints: ['app/javascript/application.js'],
inject: ['app/javascript/global.js'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure why this needs to be done in inject instead of being in the manifest file application.js ? 🤔

I am also a bit concerned about the naming of global.js as what else should go in there? Why not just name it `'app/javascript/i18n.js'?

Copy link
Contributor Author

@rosle rosle Jan 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh ok, forget about this, I should have include in comment or PR description. So there is an issue when I tried to make I18n-js works. I will try to demo step by step.

Without inject, when starting the rails app, there is an error involving with the I18n, say if I have this application.ts

import './vendor/';
import './translations/translations';

import './initializers/';
import './screens/';

console.log(I18n.t('hello'));

Screen Shot 2565-01-27 at 15 41 41

We can fix this issue by importing I18n where we need

import I18n from 'i18n-js';

But still, there will be an error on the auto-generate translation file -> /translations/translations.js This file is auto-generated from i18n js task, so we can't modify it.

So I've been looking for the old webpack config and found that we actually had it defined on ProvidePlugin to automatically loaded it everywhere.

const webpack = require('webpack');
      const plugins = [
        new webpack.ProvidePlugin({
          // Translations
          I18n: 'i18n-js',
        })
      ];
      
environment.config.set('plugins', plugins);

Then I use esbuild inject to have this same behaviour. This will load the module globally to make I18n works in the translations. That's why I named it global, so we can inject more things we need there.

Let me recheck again with the asset pipeline, maybe we can make it available -> https://github.com/fnando/i18n-js/tree/v3.9.0#rails-app-with-asset-pipeline (I've tried this but not working. But I have a new idea, maybe we can modify app/assets/config/manifest.js to load it 🤔 )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried adding require on the sprocket's app/assets/config/manifest.js but not working. As I checked, It actually does not add it to compiled application.js. Now it all depends on the esbuild to compile. Seems the app/assets/config/manifest.js can only contains link.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for all the details. We shall go with this approach then ✌️

@rosle rosle force-pushed the feature/integrate-js-bundling branch from 3a92e31 to 61f5cfa Compare January 31, 2022 04:19
@rosle rosle changed the base branch from chore/integrate-css-bundling to develop January 31, 2022 04:21
@rosle rosle force-pushed the feature/integrate-js-bundling branch from 61f5cfa to cf47a20 Compare January 31, 2022 04:22
@rosle rosle requested a review from a team February 3, 2022 07:56

require('esbuild').build({
entryPoints: ['app/javascript/application.js'],
inject: ['app/javascript/global.js'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for all the details. We shall go with this approach then ✌️

@olivierobert olivierobert requested a review from a team February 3, 2022 08:40
Copy link
Contributor

@junan junan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@rosle rosle merged commit ed3d361 into develop Feb 9, 2022
@rosle rosle deleted the feature/integrate-js-bundling branch March 18, 2022 04:01
@rosle rosle mentioned this pull request Mar 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants