00:00:09.040
Hi, my name is Justin Gordon. Welcome to my talk, 'Webpacker: It Just Works, But How?'
00:00:16.640
So why should you listen to me? Well, I know a bit about webpack, React, Ruby on Rails, and a bit about Webpacker.
00:00:22.480
I've been working on this topic since 2014 when I wrote an article about integrating webpack with Ruby on Rails.
00:00:29.519
Then, in 2015, I created the library 'React on Rails,' which is probably one of the most popular ways to integrate Ruby on Rails with React, specifically for server-side rendering.
00:00:37.120
This library has garnered about 4.2 million downloads and is being used by approximately 540,000 websites.
00:00:42.960
Since then, I've been running my own consulting company, ShakaCode, helping companies optimize their Rails websites.
00:00:48.960
My team at ShakaCode is also building Rails apps with modern front-ends, like our startup app, HiChee.
00:01:00.640
So why did I create this talk? I was working on a project for my client, Popmenu, which has restaurant websites.
00:01:08.159
This is a React on Rails site, and we were setting up loadable components for code splitting, trying to make it work with the React Refresh webpack plugin.
00:01:15.840
With that setup, we could achieve hot reloading, but it turned out to be quite challenging.
00:01:21.680
This led me to delve deeply into Rails Webpacker, and I realized I had a lot to share with you.
00:01:29.280
So, what's the problem we're solving, and what is the goal? I read a great quote today: 'When you understand the problem, what to do becomes obvious.' Understanding comes from multiple perspectives.
00:01:42.640
What we're trying to achieve is to put Rails and webpack together, aiming to make it just work. But who does it need to work for? First, it must work for the end users of web applications because slow websites lead to frustrated users who abandon them.
00:02:08.879
It also has to work well for developers; we want it to be easy to write and maintain the code.
00:02:15.040
Finally, it has to work for the Rails Webpacker maintainers, as this assists not only contributors but also serves as documentation for library users.
00:02:20.160
So, what are the main elements that make it just work? First of all, minimal to zero configuration is needed for webpack, making it easy for Rails developers.
00:02:51.200
We want Rails view helpers to support fingerprinting and bundle splitting. We also have the webpack dev server, which we want to make easy to run.
00:03:00.160
We want to ensure webpack compilation occurs when necessary and simplify project setup for production deployment. Rails has long had asset preparation with Sprockets, but Rails 6 has made Webpacker the default JavaScript bundler through the new Application JavaScript directory.
00:03:41.360
The two main components of Rails Webpacker will be orchestrating webpack to create the `manifest.json` and also handling the static assets like JavaScript and CSS files.
00:04:09.920
Additionally, we need to provide view helpers so that Rails views can display the script and link tags, indicating to the browser which files to download.
00:04:24.960
This may sound straightforward, but there are several key challenges. Firstly, the webpack output and Rails view helper output will vary based on the Rails environment.
00:04:43.200
The development environment can optimize for developer experience while the production environment should focus on the end-user experience.
00:05:04.200
Another challenge is the webpack dev server for development, differing from the static asset creation that happens in the public directory.
00:05:11.360
During development, assets may either be served from the public directory or from the webpack dev server; I'll elaborate on that shortly.
00:05:34.800
And lastly, there's the challenge of creating a separate bundle for server rendering, which involves creating distinct files.
00:05:42.960
So, what does the overall Rails Webpacker flow look like? I'll refer back to this diagram frequently throughout the talk. The key point is orchestrating webpack.
00:06:14.880
We'll set some settings in a `config/webpacker.yml` file. This was done because both Rails and the JavaScript code need to access that configuration.
00:06:37.360
In conjunction with the JavaScript files that will configure webpack, they reside within the Rails Webpacker libraries alongside other Ruby code.
00:06:49.120
These will create a webpack config object which will then run webpack, generating the `manifest.json` and the static assets that Rails needs. This will construct the HTML that gets sent to Rails, creating the correct asset tags, whilst ensuring Rails is ready to serve the statically created assets.
00:06:54.640
Let me show you a demonstration of the end result. I've built a sample application on GitHub: ShakaCode/webpacker-examples.
00:07:14.960
I'll start up Rails. I've cleared out my webpack directory in public, so the files are absent, making it necessary for webpack to compile.
00:07:54.240
Let's hit refresh. Now, notice that Webpacker is compiling.
00:08:00.960
Everything appears to be up to date, but if I check this in the network tab, I can view what files were served.
00:08:41.280
If I then view the page source, this shows what we wanted to achieve within the HTML generated by Rails.
00:08:52.960
We see the link to the files created by webpack—this is the magic of Rails Webpacker orchestrating webpack and ensuring the necessary files are available on our web page.
00:09:03.520
Now, how do the new view helpers function? Currently, we're focused on how Rails delivers the HTML with proper asset tags and how Rails serves the assets for the web page.
00:09:12.960
Let’s dive deeper. In our view, specifically the `index.html.erb`, we'll use the Rails Webpacker helper method `stylesheet_pack_tag`, which references our 'home' string.
00:09:36.160
This 'home' corresponds to our file situated in the packs directory, forming our entry point. Consequently, the public development `manifest.json` produced by webpack will contain an entry labeled 'home'.
00:09:58.560
The `config/webpacker.yml` includes a public output path for development, where the files generated by webpack are stored, directly impactful for Rails’ public assets.
00:10:25.840
This connection between the `manifest.json`, public output path, and view helpers results in the HTML delivered to the browser. As I just mentioned, the HTML the browser renders shows the webpack development runtime for home that directly corresponds to this `manifest.json`.
00:11:08.320
Additionally, if you review those chunk files, you'll see examples in the project I provided. One page contains moment.js, another page contains both lodash and moment.js, and yet another page does not include either.
00:11:46.240
This results in several distinct chunks. Therefore, depending on the page being accessed, we send only the necessary JavaScript to the browser.
00:12:04.400
It would be inefficient to send all JavaScript files as someone might never access certain pages. This showcases a key difference when utilizing Sprockets, which lacks this automated chunking feature.
00:12:15.440
How does webpack know to enact this proper functionality? Let’s explore the overarching roadmap for Rails Webpacker and how the webpack library orchestrates webpack to produce the right output fed into Rails.
00:12:50.880
First, we establish our configuration; it involves multiple JavaScript files that correspond to different environments. The only environment-specific files are `development.js`, `production.js`, and `test.js`.
00:13:16.240
The `environment.js` file serves as the common file imported by both development and production configurations. Remember, the `config/webpacker.yml` file contains essential standard directories and other configurations that are vital on the JavaScript side.
00:14:31.320
On the client-side, there are also entry points; the entry point example of 'home' is straightforward.
00:14:37.680
It does not include additional complexities found in the examples utilizing lodash and moment. A crucial file here is the `package.json`, which grants access to numerous modules.
00:14:49.840
So what happens is that all these files, JavaScript files, images—everything—are funneled into webpack, ultimately generating multiple files in your public webpack directory.
00:15:13.440
Most importantly, it generates this manifest file that allows Rails to map specific files to bundles.
00:15:53.120
How does webpack actually run? By installing Rails Webpacker, a bin file called `bin/webpack` is created.
00:16:11.040
This file calls the webpack runner with the necessary arguments and loads the appropriate webpack configuration based on your node environment.
00:16:23.440
Remember, this is not your Rails environment; you can configure your node environment to determine the output generated by webpack and your JavaScript files.
00:16:49.040
For example, the `development.js` file will correlate with the development environment configuration, as mentioned earlier.
00:17:05.200
This overall orchestration flow is responsible for preparing those files for Rails, specifically the `production.js` file that contains production-specific configurations.
00:17:37.680
It references the common `environment.js` file I previously mentioned, ensuring a shared foundation.
00:18:01.920
The key takeaway is that the output—this file in line five ultimately exports a straightforward JavaScript object representing the webpack configuration.
00:18:24.400
That webpack configuration can be examined in precise detail over at the webpack site, specifically webpack.js.org/configuration.
00:19:00.560
In the `environment.js` file, this is where you place customizations applicable to all environments.
00:19:28.080
Now let's delve under the hood and take a closer look at what happens under the surface.
00:19:56.960
Suppose we want to inspect the webpack configuration for debugging.
00:20:22.480
To do that, I will exit the Rails app and run `bin/webpack --debug`.
00:20:44.560
By running this, the debugger opens, and I've made some adjustments, setting the default setup to export environment to the webpack config while allowing me to inspect it.
00:21:20.080
You can inspect it directly in the console for more space. The webpack configuration provides details about file names, including public paths.
00:21:35.760
Importantly, you can see the environment plugins that could include different other settings. This configuration is ultimately a nested JavaScript object, not merely a plain JSON file.
00:21:52.080
Using the inspector helps clarify the structure, and you may visit webpackjs.org to reference documentation.
00:22:15.920
The entry points, configured by the packs directory, tie the documentation to the actual object defined there.
00:22:59.440
As I referred to earlier, that object is produced through executing Rails Webpacker, unifying these files to generate this config object destined for webpack.
00:23:14.240
Another point to note is regarding your `package.json`; sometimes it appears lacking in webpack or Babel plugins and their specific versions.
00:24:06.320
When including dependencies from node modules, it's akin to Ruby gems, where various dependencies can reside.
00:24:30.080
To accurately discern what dependencies are being pulled in, especially for Rails Webpacker, maintain awareness of how dependencies specify plugins, including the webpack version.
00:25:02.440
A recommended first step is to check the official GitHub repository for the Rails Webpacker project and ensure browsing the correct version number corresponding to your webpack version.
00:25:36.720
Currently, as of this recording, Webpacker is at version 5.1.1. If running on version 4 and checking out the master file, discrepancies in documentation versions could cause issues.
00:26:11.440
Another option to assess this is running `npm ls webpack` or similar commands to identify included versions.
00:26:44.080
Take caution; the webpack documentation lacks easy access to older versions.
00:27:01.920
While there are not frequent changes from version to version, keeping them in mind is wise.
00:27:30.480
If you wish to override included versions being pulled from webpack, yarn resolutions allow you to specify desired versions directly.
00:27:51.760
To maintain coherence with the standard Webpacker configurations, it's advisable to keep deviations minimal, focusing primarily on JavaScript configurations over the `webpacker.yml` setup.
00:28:30.720
Creating separate bundles for client and server rendering using Rails Webpacker is achieved via the webpack multi-compiler.
00:29:05.400
This process allows webpack to export an array of configurations instead of being limited to a single object.
00:29:39.120
For instance, merging the client environment with a basic webpack config will create a client specific configuration, while keeping a server configuration independent.
00:30:17.760
It's not uncommon to require different setups for client and server bundling, especially in the context of server-side rendering.
00:30:56.640
Another common inquiry revolves around whether view helpers can be utilized separately from Rails Webpacker configurations, and the answer is yes.
00:31:33.920
Many of my React on Rails clients require customized webpack configurations, leading me to devise approaches for leveraging the Rails Webpacker library while keeping the complete webpack config separate.
00:32:10.880
It’s entirely feasible to draw upon the Rails Webpacker Node package. The pivotal part is ensuring the right `manifest.json` is generated.
00:32:54.560
Moreover, if seeking to incorporate hot reloading, paying close attention to utilizing that node package is critical.
00:33:32.160
What’s the ideal method for running Rails during development? Earlier, I demonstrated how running `rails s` works, turning compilation on.
00:34:12.720
Facilitating the web request means that if some JavaScript changes synchronize from GitHub, having the compile option set to true will cause webpack compilation to be skipped.
00:34:50.480
If the webpack dev server is inactive, Rails computes a cache key for your assets, consuming time by reading each client file.
00:35:09.840
This procedure can be noticeably slow if numerous files are present. The compilation process I demonstrated pops up retaining cache keys from past operations.
00:35:36.480
At the end of the day, the serving time on Rails can prolong significantly if the compile option is engaged without taking into account the subsequent options.
00:36:16.400
Option two is to run webpack in watch mode by launching `rails s` in one terminal and `bin/webpack watch` in another.
00:36:41.920
This ensures webpack actively regenerates the bundles anytime a file is saved. Option three involves running Rails in one terminal while the webpack dev server operates in another.
00:37:07.440
When the webpack dev server runs, it computes the bundles proactively, similar to watch mode, but serves as a mini web server for your assets.
00:37:39.920
However, when examining the source of your Rails output while the dev server is active, nothing visibly differs—this aspect showcases the 'magic' of Rails Webpacker.
00:38:12.160
Notably, Rails skips the webpack compilation if the compile option is set to false, with Rails Webpacker pragmatically checking whether the dev server runs on localhost at port 3035.
00:38:55.520
To maintain seamless integration, Rails Webpacker ensures asset management remains stable, utilizing a proxy to the webpack dev server.
00:39:12.960
This proxy setup occurs within the Rails Webpacker's Railtie initializer, facilitating smooth configurations through the YAML settings.
00:39:41.920
In conclusion, if your development JS file is sparse, remember that the vital settings derived from the environment package relate back to the Rails Webpacker Node library.
00:40:16.640
These configurations are not merely default; they are tailored to per-environment specifics, whether it be development or production.
00:40:40.160
The final aspect of Rails Webpacker magic centers around asset deployment. You might have used `rake assets:precompile` for deployment previously.
00:41:07.520
However, Rails Webpacker automates this process for you. There's a `compile.rake` file within the Rails Webpacker source code.
00:41:32.560
This file contains the method `def enhance_assets_precompile`, integrating dependency management to ensure Yarn installation.
00:41:56.880
It subsequently calls the Webpacker compile task, orchestrating webpack to construct all assets.
00:42:17.920
Congratulations, you've almost reached the end of my Rails Webpacker presentation. To recap, the main components of the overall flow begin with the `config/webpacker.yml` file.
00:43:01.280
This file is crucial as it comprises values that the Ruby on Rails server and JavaScript code will read to configure the webpack configuration object.
00:43:28.720
You will also have individual files for each node environment—development, test, and production—allowing for further customization of webpack.
00:44:06.160
This orchestration leads to the creation of our configuration object that gets fed into webpack.
00:44:28.480
This process generates the `manifest.json` and additional static assets such as JavaScript, CSS, fonts, and images necessary for the browser.
00:45:03.920
The Rails server utilizes this asset information from the manifest to execute appropriate asset tags in the pages sent to the browser.
00:45:37.520
Because Rails Webpacker efficiently configures webpack, the actual static assets are stored directly in the public directory, ready for integration.
00:46:15.440
Thank you for joining this talk; I hope you now have a clear understanding of how to harness Rails and webpack using the Rails Webpacker gem and Node modules.
00:47:03.920
My wish is to aid you in effectively configuring your assets to ensure your client-side components are optimized for all environments.
00:47:46.720
I recognize there may be some complications, and this presentation aims to guide you in avoiding unnecessary challenges.
00:48:01.920
On the final slide, I've provided resources should you encounter any issues with Rails Webpacker, server-side rendering, or enhancing performance.
00:48:11.920
Feel free to explore the links to an invite for a Slack workspace, a forum I'll attempt to contribute to, and my email for any direct inquiries.
00:48:32.160
This area has been my niche for a long time, and I'm eager to help you with your Webpackers inquiries. Thank you once more for attending.
00:49:00.000
If you obtain the slides, you'll encounter bonus slides that cover aspects beyond those discussed in the talk.
00:49:39.840
A quick appreciation to JetBrains, ShakaCode's clientele, and other contributors. You can find the details in the slides.
00:50:03.200
Thank you once again for being here, and I hope you experience minimal yak shaving with Rails Webpacker moving forward!
00:50:25.760
Goodbye!