Since Webpacker
is used in Rails apps, you would want not only to add vite
from NPM, but also the ancillary dependencies.
The easiest way to do this is to 1) add the vite_ruby
gem to your Gemfile or gemspec, then run bundle
, then 2) run bundle exec vite install
. /This will take care of adding the other dependencies needed to get started./
Following the above steps will do these things for your app:
- Install necessary dependencies to begin using
vite
withRails
, which includes some nice helpers - Infer that
app/javascript
is your JS/TS root source directory and create a configuration for that namedvite.json
- Generate a
vite.config.ts
file which is where you can make use of Vite plugins and configure how things are compiled. - Generate (based on the root source directory config) an
entrypoints
directory which is essentially the same as thepacks
directory for Webpacker.- Generate
application.js
andapplication.css
files inside of this directory which are intended to be the main entry points for your application JS/TS & CSS.
- Generate
Although it will be easiest to do this, you do not have to move everything into the app/javascript/entrypoints
directory.
To keep your components where they are, you simply need to add the additionalEntrypoints
list to vite.json
like so:
"additionalEntrypoints": [
"app/javascript/components/**/*.tsx",
]
This will make things easier for the transition and will allow Vite to find and compile any source that is matched. (Note: typical glob rules apply)
Like webpack
, you can create aliases just the same way to make imports like this:
import Foo from '../../../helpers/foo'
into:
import Foo from 'helpers/foo'
This can be configured in vite.config.ts
like so:
export default defineConfig({
...
resolve: {
alias: {
'helpers': resolve(__dirname, 'app/javascript/helpers'),
}
}
})
So now you have a whole bundle of Webpacker assets that no longer need to be in your app. You will want to remove the libraries:
webpacker
react_rails
(see below for alternative)@babel/preset-env
and family from.babel.config.js
@rails/webpacker
webpack
- any webpack loaders
react_ujs
we didn’t need thiswebpack-dev-server
- anything else with
webpack
in it’s name 🔥
Also, delete these directories:
config/webpacker.yml
config/webpacker
app/javascript/packs
- move any other entries here to theentrypoints
directory
As mentioned here, vite_ruby
provides nice helpers to load JS/TS and (S)CSS.
These are likely the tags you will need for your app to properly function:
vite_stylesheet_tag “application.scss”
vite_typescript_tag “application.ts”
vite_client_tag
For your first view, choose something simple and add a tag for it in the view (*assuming ERB here and assuming you have created an alias for “components” or the directory is under entrypoints
):
<%= vite_typescript_tag "components/Foo/index" %>
This will place the JavaScript tag in the HTML output of the view and the extension, in this case, will be .ts
No need to worry! This is simply a field in the Vite manifest entry which, depending on how your component is structured, will have one or more linked file names inside. This is the “recipe” for your component and all recipes contain ingredients or “assets” in our case. The result will be compiled JS/CSS which will execute/render in the browser as expected.
We were not able to get this properly working (yet) likely due to conflicts with Turbolinks. It isn’t a critical feature and can be pursued any any time. Failed HMR will simply be full page reload.
Normally, you would use react-rails
like so (assuming ERB)
<%= react_component("Foo/index", @props) %>
Which spits out a data infused <div>
into wherever the tag resides within the HTML hierarchy. Following this, the library runs a script that locates each <div>
in the DOM tree then applies the parsed JSON as props
to each applicable React component via the react-dom
library.
react-rails
doesn’t support Vite.js, so we created a WIP alternative which does the same.
This alternative is two-part, so the client-side part is found here
As you can see, we are relying on Turbolinks events in the above example to fire before we query the DOM to find any applicable React components to hydrate.
More optimization will come!
In my brief overview, I explained the different steps to replacing Webpacker in your app with Vite.js. This guide isn’t intended as a complete step-by-step instruction manual, but does highlight most of the main features needed to get your app up and running quickly. If you have any questions, feel free to reach out!
Stephen (@thestephenmarshall)