Skip to content

Latest commit

 

History

History
171 lines (124 loc) · 11.4 KB

v6_upgrade.md

File metadata and controls

171 lines (124 loc) · 11.4 KB

Upgrading from Webpacker v5 to Shakapacker v6

There are several substantial changes in Shakapacker v6 that you need to manually account for when coming from Webpacker 5. This guide will help you through it.

ShakaCode offers support for upgrading from webpacker or using Shakapacker. If interested, contact [email protected].

Webpacker/Shakapacker has become a slimmer wrapper around Webpack

By default, Webpacker 6 is focused on compiling and bundling JavaScript. This pairs with the existing asset pipeline in Rails that's setup to transpile CSS and static images using Sprockets. For most developers, that's the recommended combination. But if you'd like to use Webpacker for CSS and static assets as well, please see integrations for more information.

Webpacker used to configure Webpack indirectly, which lead to a complicated secondary configuration process. This was done in order to provide default configurations for the most popular frameworks, but ended up creating more complexity than it cured. So now Webpacker delegates all configuration directly to Webpack's default configuration setup. Additionally, all major dependencies, like webpack and babel are now peer dependencies, so you are free to upgrade those.

While you have to configure integration with frameworks yourself, webpack-merge helps with this. See this example for Vue and scroll to the bottom for more examples.

webpacker v6.0.0.rc.6 to shakapacker v6.0.0

See an example migration here: PR 27.

Update Steps to v6.0.0 from v6.0.0.rc.6

If you're on webpacker v5, follow below steps to get to v6.0.0.rc.6 first.

  1. Change the gem name from webpacker to shakapacker and the NPM package from @rails/webpacker to shakapacker.
  2. Install the peer dependencies. Run yarn add @babel/core @babel/plugin-transform-runtime @babel/preset-env @babel/runtime babel-loader compression-webpack-plugin terser-webpack-plugin webpack webpack-assets-manifest webpack-cli webpack-merge webpack-sources webpack-dev-server. You may have old versions of libraries. Run yarn install and check for warnings like warning " > [email protected]" has incorrect peer dependency "compression-webpack-plugin@^9.0.0" and [email protected]" has incorrect peer dependency "webpack@^2.0.0 || ^3.0.0 || ^4.0.0". In other words, warnings like these are serious and will cause considerable confusion if not respected.
  3. Update any scripts that called bin/webpack or bin/webpack-dev-server to bin/webpacker or bin/webpacker-dev-server
  4. Update your webpack config for a single config file, config/webpack/webpack.config.js. If you want to use the prior style of having a separate file for each NODE_ENV, you can use this shim for config/webpack/webpack.config.js. WARNING, previously, if you did not set NODE_ENV, NODE_ENV defaulted to development. Thus, you might expect config/webpack/development.js to run, but you'll instead be using the config/webpack/RAILS_ENV.js
    const { env, webpackConfig } = require('shakapacker')
    const { existsSync } = require('fs')
    const { resolve } = require('path')
    
    const envSpecificConfig = () => {
      const path = resolve(__dirname, `${env.nodeEnv}.js`)
      if (existsSync(path)) {
        console.log(`Loading ENV specific webpack configuration file ${path}`)
        return require(path)
      } else {                       
        // Probably an error if the file for the NODE_ENV does not exist
        throw new Error(`Got Error with NODE_ENV = ${env.nodeEnv}`);
      }
    }
    
    module.exports = envSpecificConfig()
  5. Update babel.config.js if you need JSX support. See Customizing Babel Config

How to upgrade to Webpacker v6.0.0.rc.6 from v5

  1. Ensure you have a clean working git branch. You will be overwriting all your files and reverting the changes that you don't want.

  2. Ensure no nested directories in your source_entry_path. or set option nested_entries: true Check if you had any entry point files in child directories of your source_entry_path.

    The new v6 configuration defaults to not allow nesting, so as to allow placing the entry points at in the root directory of JavaScript. You can find this change here.

  3. Upgrade the Webpacker Ruby gem and the NPM package

    Note: Check the gem page to verify the latest version, and make sure to install identical version numbers of shakapacker gem and package. (Gems use a hyphen and packages use a dot between the main version number and the beta version.)

    Example going to a specific version:

    # Gemfile
    gem 'shakapacker', '6.0.0.rc.13'
    bundle install
    yarn add [email protected] --exact
    bundle exec rails webpacker:install

    Overwrite all files and check what changed.

    Note, the webpacker:install will install the peer dependencies:

    yarn add @babel/core @babel/plugin-transform-runtime @babel/preset-env @babel/runtime babel-loader compression-webpack-plugin terser-webpack-plugin webpack webpack-assets-manifest webpack-cli webpack-merge webpack-sources webpack-dev-server
  4. Review the new default's changes to webpacker.yml. Consider each suggested change carefully, especially the change to have your source_entry_path be at the top level of your source_path. The v5 default used packs for source_entry_path:

    source_path: app/javascript
    source_entry_path: packs

    The v6 default uses the top level directory.

    source_path: app/javascript
    source_entry_path: /

    If you prefer this configuratiom, then you will move your app/javascript/packs/* (including application.js) to app/javascript/ and update the configuration file.

    Note, moving your files is optional, as you can stil keep your entries in a separate directory, called something like packs, or entries. This directory is defined with the source_path.

  5. Ensure no nested directories in your source_entry_path. Check if you had any entry point files in child directories of your source_entry_path. Files for entry points in child directories are not supported by shakacode/shakapacker v6. Move those files to the top level, adjusting any imports in those files.

    The v6 configuration does not allow nesting, so as to allow placing the entry points at in the root directory of JavaScript. You can find this change here.

  6. Update webpack-dev-server to the current version, greater than 4.2, updating package.json.

  7. Update API usage of the view helpers by changing javascript_packs_with_chunks_tag and stylesheet_packs_with_chunks_tag to javascript_pack_tag and stylesheet_pack_tag. Ensure that your layouts and views will only have at most one call to javascript_pack_tag and at most one call to stylesheet_pack_tag. You can now pass multiple bundles to these view helper methods. If you fail to changes this, you may experience performance issues, and other bugs related to multiple copies of React, like issue 2932. If you expose jquery globally with expose-loader, by using import $ from "expose-loader?exposes=$,jQuery!jquery" in your app/javascript/application.js, pass the option defer: false to your javascript_pack_tag.

  8. If you are using any integrations like css, postcss, React or TypeScript. Please see https://github.com/shakacode/shakapacker#integrations section on how they work in v6.

  9. config/webpack/environment.js was changed to config/webpack/base.js and exports a native webpack config so no need to call toWebpackConfig. Use merge to make changes:

    // config/webpack/base.js
    const { webpackConfig, merge } = require('@rails/webpacker');
    const customConfig = {
      module: {
        rules: [
          {
            test: require.resolve('jquery'),
            loader: 'expose-loader',
            options: {
              exposes: ['$', 'jQuery']
            }
          }
        ]
      }
    };
    
    module.exports = merge(webpackConfig, customConfig);
  10. Copy over custom browserlist config from .browserslistrc if it exists into the "browserslist" key in package.json and remove .browserslistrc.

  11. Remove babel.config.js if you never changed it. Configure your package.json to use the default:

    "babel": {
      "presets": [
        "./node_modules/@rails/webpacker/package/babel/preset.js"
      ]
    }

    See customization example the Customizing Babel Config for React configuration.

  12. extensions was removed from the webpacker.yml file. Move custom extensions to your configuration by merging an object like this. For more details, see docs for Webpack Configuration

    {
      resolve: {
        extensions: ['.ts', '.tsx', '.vue', '.css']
      }
    }
  13. In webpacker.yml, check if you had watched_paths. That is now additional_paths.

  14. Some dependencies were removed in PR 3056. If you see the error: Error: Cannot find module 'babel-plugin-macros', or similar, then you need to yarn add <dependency> where might include: babel-plugin-macros, case-sensitive-paths-webpack-plugin, core-js, regenerator-runtime. Or you might want to remove your dependency on those.

  15. Review the new default's changes to webpacker.yml and config/webpack. Consider each suggested change carefully, especially the change to have your source_entry_path be at the top level of your source_path.

  16. Make sure that you can run bin/webpack without errors.

  17. Try running RAILS_ENV=production bin/rails assets:precompile. If all goes well, don't forget to clean the generated assets with bin/rails assets:clobber.

  18. Run yarn add webpack-dev-server if those are not already in your dev dependencies. Make sure you're using v4+.

  19. In bin/webpack and bin/webpack-dev-server, The default NODE_ENV, if not set, will be the RAILS_ENV. Previously, NODE_ENV would default to development if not set. Thus, the old bin stubs would use the webpack config corresponding to config/webpack/development.js. After the change, if RAILS_ENV is test, then NODE_ENV is test. The final 6.0 release changes to using a single webpack.config.js.

  20. Now, follow the steps above to get to shakapacker v6 from webpacker v6.0.0.rc.6

Examples of v5 to v6

  1. React on Rails Project with HMR and SSR
  2. Vue and Sass Example