Upgrade to Pro — share decks privately, control downloads, hide ads and more …

rubyconf_nairobi.pdf

 rubyconf_nairobi.pdf

Prathamesh Sonpatki

July 26, 2019
Tweet

More Decks by Prathamesh Sonpatki

Other Decks in Programming

Transcript

  1. ! Hello!!! Welcome to the second day of Ruby Conf

    Nairobi 2019. Welcome! Thank you for coming for my talk.
  2. Prathamesh Sonpatki Pune Part of Ruby community Rails issues team.

    Marathon Kenya beat west indies in Pune in 1996. It was big upset.
  3. Prathamesh Sonpatki Memory.ai timelyapp.com Work at Memory. AI Powered tools

    to solve the problem of abuses of time and help everyone produce meaningful work.
  4. Prathamesh Sonpatki Pokemon Go! Become my friend, meet me after

    my talk and let’s catch some pokemon.
  5. We don’t do that here We don’t do it in

    real life. It is only in movies. Discussion about movies at speaker dinner.
  6. prathamesh.tech/movies @_cha1tanya So On popular demand list of movies you

    should watch, You can tweet me and I will add that movie to the list.
  7. State of the art of managing assets in new Rails

    world Alright, let’s talk about the actual topic now.
  8. Rails 6 Rails 6 is just around the corner. The

    release candidate two was released just two days back. As this is a major release, it is packed with so many interesting features.
  9. Rails 6 Action Text for rich text editor support Action

    MailBox for accepting emails in our web app
  10. We are going to talk today about a significant change

    which impacts the way we manage our frontend code. It is about webpacker.
  11. The relationship between Rails and JavaScript has been like Tom

    and Jerry. They don’t love each other fully but also have to make peace with each other because they have to live together.
  12. Rails 1 RJS How many of you have used Rails

    1? It had a Ruby to JS template system where you write Ruby which generates JavaScript which is evaled by browser in a response to an Ajax request.
  13. Rails 3.1+ Asset Pipeline In Rails 3.1 asset pipeline was

    introduced to solve the problem of managing assets.
  14. The release notes rightly mentioned that time that now JavaScript

    and other assets are integral part of the application.
  15. Asset pipeline The asset pipeline provided a framework to concatenate

    and minify or compress JavaScript and CSS assets.
  16. Asset pipeline It also added the ability to write these

    assets in other languages and pre-processors such as CoffeeScript, Sass and ERB.
  17. Asset pipeline It allowed assets in your application to be

    automatically combined with assets from other gems. Remember jquery-rails or bootstrap-rubygem or underscore-rails?
  18. But the web development landscape was changing extremely fast. JavaScript

    was the driving force for almost all of the web applications.
  19. Rails was also catching up. Sprockets was able to understand

    ES6 syntax though it was experimental.
  20. Asset pipeline People used different workaround to take advantage of

    latest JS ecosystem. Using CDN builds was one option. Using rails-assets.org with bower was one option that used for some time. There were also unofficial integrations with browserify or webpack
  21. Asset pipeline But it was always going to be behind

    the JavaScript train. It was like we are wrapping the JavaScript world in a Ruby gem and the Javascript world just exploded.
  22. Asset pipeline But it was always going to be behind

    the JavaScript train. It was like we are wrapping the JavaScript world in a Ruby gem and the Javascript world just exploded.
  23. let’s flip the problem. Instead of fighting with JS let’s

    embrace it. That’s what Rails team did. To understand how they did it we need to understand what sprockets does for us.
  24. Asset pipeline Essentially sprockets does two things for us. Managing

    all of the dependencies in our code and then packaging them so that a single file can be deployed after compiling and running all the post processing tools.
  25. Asset pipeline Dependency management Essentially sprockets does two things for

    us. Managing all of the dependencies in our code and then packaging them so that a single file can be deployed after compiling and running all the post processing tools.
  26. Asset pipeline Dependency management Modularization Essentially sprockets does two things

    for us. Managing all of the dependencies in our code and then packaging them so that a single file can be deployed after compiling and running all the post processing tools.
  27. 
 # app/assets/javascripts/application.js //= require moment-rails //= require jquery-rails //=

    require underscore-rails In theory everyone should be using //= require statement at the top of their file to declare the dependencies of their file, but in my experience this starts breaking down in big projects and people rely on certain things always being available. We are basically relying on globals to be available so that the concatenation works.
  28. Facebook was working on a package manager around that time,

    it was released as yarn. Yarn tried to solve problems caused by npm like lockfile, reliability.
  29. yarn Rails 5.1+ Rails app and sprockets were able to

    understand package.json Yarn had proper lock file like bundler and it was created facebook to solve the unreliability with npm. Though npm improved in latter releases.
  30. Modularization code organized in multiple files to a user's web

    browser. We also want to use third party libraries like jQuery. The way bundling JavaScript works in Sprockets is that it concatenates all the files together, relying on the programmer to assign and reference global variables in each file,
  31. # app/assets/javascripts/make_coffee.js $(“#coffe_maker”).click( {} ); jQuery is available globally. In

    theory everyone should be using //= require statement at the top of their file to declare the dependencies of their file, but in my experience this starts breaking down in big projects and people rely on certain things always being available. We are basically relying on globals to be available so that the concatenation works.
  32. There are some problems with this. Whether to use third

    party libs directly in script tags or in vendor files or in my bundle? I
  33. Not possible to write unit tests as everything relies on

    global scope. Not easy to use new hot things like Typescript
  34. Modules What we need is ability to create modules and

    use them with each other to manage different parts of code. But having module system is not the only challenge, browsers also need to understand it. And we know that browsers heavily rely on global objects. Let’s see an example.
  35. // version.js module.exports = { version: ‘1.0’ } This simple

    code shows us how modules can be defined. This works fine in server side code. But to make this work with browsers we need tools that will resolve this require or import calls and make browsers understand them.
  36. // version.js module.exports = { version: ‘1.0’ } // application.js

    var config = require(‘./version.js’) console.log(config.version) We can use the module like this.
  37. That’s where web pack comes into the picture. Webpack gives

    us ability to modularize the code. It also implements a way to translate JavaScript code that doesn't work in any web browser to JavaScript code that works in most web browsers.
  38. Webpack has tons of configurations to do lot of things.

    So it is hard to use and hard to understand. But nothing in Webpack “just works”—you have to provide configuration for Webpack's most basic features to work.
  39. Make Webpack Rails friendly This means we'll be spending a

    lot of time in documentation and a lot of time making decisions that have nothing to do with our users or the problems we're trying to solve for them. As a consequence, it is fairly complex to configure from scratch making it somewhat of an odd choice for Rails, which promotes convention over configuration. Webpacker fills the gap.
  40. The gem introduces some conventions and abstracts away a default

    configuration to make it easier to get up-and-running with
  41. It also forms bridge between web pack and rails app

    so that we can include the output generated by webpack in the Rails app as we will see shortly.
  42. rails new my_app —webpack Rails 5.1+ When it was introduced

    in Rails 5.1, We can create a new Rails app with web pack to manage the JavaScript code like this.
  43. rails new my_app Rails 6 In Rails 6, that’s it.

    Webpack is enabled by default.
  44. rails webpacker:install create config/webpacker.yml Copying webpack core config create config/webpack

    create config/webpack/development.js create config/webpack/environment.js create config/webpack/production.js create config/webpack/test.js When web packer is installed, it sets up common conventions and configurations for different environments and default options for web pack.
  45. yarn add v1.17.3 info No lockfile found. [1/4] Resolving packages...

    ⠁ @rails/actioncable@^6.0.0-alpha warning @rails/webpacker > postcss-preset-env > postcss- color-functional-notation > postcss-values-parser > [email protected]: I wrote this module a very long time ago; you should use something else. [2/4] Fetching packages... [3/4] Linking dependencies... [4/4] Building fresh packages... success Saved lockfile. success Saved 602 new dependencies. info Direct dependencies !" @rails/[email protected] !" @rails/[email protected] !" @rails/[email protected] !" @rails/[email protected] #" [email protected] It also sets up required npm packages using yarn. This includes all packages that Rails itself depends on.
  46. app/javascript It also creates a new directory app/javascript which hosts

    our javascript code now. Earlier it was app/assets/javascripts now it is app/javascript. You might be wondering why the javascript in the directory name instead of assets or say javascripts?
  47. Because it is part of the application written in JavaScript

    the language as DHH says here. It is very significant statement as it acknowledges javascript part of the application as equal partner in the relationship.
  48. app/javascript But <em>Also</em> the name suggests, The web packer is

    only meant to manage our JavaScript code not the other assets like font/images. They are still managed by asset pipeline like before. In that way, we still have assets pipeline enabled in Rails 6 but only for non-javascript assets.
  49. Entry point Webpack entry point is where web pack looks

    to start building the bundle The convention here is that all webpack entry points should be placed in the app/*javascript/*packs folder and the modules can be placed inside app/*javascript folder in any way you like.
  50. app/javascript/packs Webpack entry point is where web pack looks to

    start building the bundle The convention here is that all webpack entry points should be placed in the app/*javascript/*packs folder and the modules can be placed inside app/*javascript folder in any way you like.
  51. app/javascript/packs/admin.js app/javascript/packs/client.js Separate packs for separate pages and web pack

    will create bundles automatically. We don’t need to include them in config.assets_precompile list
  52. app/javascript/packs/application.js Rails by default creates application pack. This is equivalent

    to application.js created with sprockets. // This file is automatically compiled by Webpack, along with any other files // present in this directory. You're encouraged to place your actual application // logic in a relevant structure within app/javascript and only use these pack files to // reference that code so it'll be compiled. This configuration is provided by webpacker by default.
  53. # app/javascript/packs/application.js import 'common/util'; We can include it in our

    application pack like this. This will tell webpack to load it while preparing the bundle.
  54. Rendering it on page The next step is making sure

    that we include the bundle generated by web pack in our HTML page.
  55. <%= javascript_pack_tag 'application', 'data-turbolinks-track': ‘reload' %> We can tell Rails

    to include the bundle generated by webpack by using a pack tag. This helper method is provided by webpacker and takes care of inserting the JavaScript into our page similar to javascript_link_tag
  56. bundle exec rails webpacker:install:react Webpacker provides out of the box

    integrations with most of the popular JS frameworks.
  57. bundle exec rails webpacker:install:vue Webpacker provides out of the box

    integrations with most of the popular JS frameworks. It supports elm, vue, stimulus.
  58. Webpacker provides out of the box integrations with most of

    the popular JS frameworks. It supports elm, vue, stimulus.
  59. + So if you have existing legacy code, then you

    can start adding new code under app/javascript and keep old code as it is.
  60. + Or you can start migrating some of the legacy

    code to webpack and then remove it from assets pipeline.
  61. import moment from ‘moment'; moment().calendar() Need to include it everywhere

    moment is used. Because global scope does not work.
  62. require_context It allows you to pass in a directory to

    search, a flag indicating whether subdirectories should be searched too, and a regular expression to match files against.
  63. bundle exec rails assets:precompile Rails provides a rake task to

    precompile assets from asset pipeline. Webpacker adds webpacker:compile task to the assets:precompile task. It gets run every time you run assets:precompile.
  64. brew install yarn Yarn will be needed on the server

    we are trying to deploy, Nodes as well Heroku does this out of the box. So it just works. It also supports docker, cloud9, capistrano
  65. ▶ ./bin/webpack-dev-server ℹ 「wds」: Project is running at http://localhost:3035/ ℹ

    「wds」: webpack output is served from /packs/ ℹ 「wds」: Content not from webpack is served from /Users/prathamesh/ Projects/scratch/blog/public/packs ℹ 「wds」: 404s will fallback to /index.html ℹ 「wdm」: Hash: f8c6a1b1755dc32681d6 Version: webpack 4.36.1 Time: 3240ms Built at: 07/23/2019 3:13:42 PM Asset Size Chunks Chunk Names js/application-2d8c7ac24fdd30370b2e.js 504 KiB application [emitted] application js/application-2d8c7ac24fdd30370b2e.js.map 568 KiB application [emitted] application manifest.json 364 bytes [emitted] ℹ 「wdm」: Compiled successfully. Compiles on demand,
  66. Tree shaking Tree shaking is fancy term for dead code

    elimination. Enabled by default by webpacker.
  67. Code splitting Code splitting is one of the most compelling

    features of webpack. This feature allows you to split your code into various bundles which can then be loaded on demand or in parallel. It can be used to achieve smaller bundles and control resource load prioritization which, if used correctly, can have a major impact on load time. This also works with web packer as it allows multiple entry points.
  68. Rails has fully embraced js for js Time for you

    to invest some time in learning webpack. It is not one to one mapping between assets and webpack. When to use webpacker and when to use sprockets. What web pack brings to the table Modularization