# sewing_kit [![Build status](https://badge.buildkite.com/e7cdc87e61b9fe80e91e8686b6bfba53ca26a36366eb811a50.svg)](https://buildkite.com/shopify/sewing-kit-gem-ci) Zero configuration, high performance front end development at organization scale. `sewing_kit` can be used in a Rails application instead of [Webpacker](https://github.com/rails/webpacker), allowing to embed bundled/compiled javascript in erb pages. For a more complete and modern stack with performance-as-a-feature, consider [quilt_rails](https://github.com/Shopify/quilt/tree/master/gems/quilt_rails). For details on configuring and usage of the `sewing-kit` node package, see the [sewing-kit README](/README.md). ## Quick Start Create a Rails project using `dev init` then: ### Install Sewing Kits ```sh # Add Ruby/Node dependencies bundle add sewing_kit yarn add @shopify/sewing-kit yarn dev up ``` ### Run generator `rails generate sewing_kit:install` will generate a package.json file with common sewing-kit script tasks, default lint, format configuration; a sewing-kit configuration file, and other project default configurations. ### Add JavaScript sewing_kit looks for JavaScript in `app/ui/index.js`. The code in `index.js` (and any imported JS/CSS) will be built into a `main` bundle. ### Link to JS/CSS with `erb` Helpers The `main` bundle is imported into `erb` files using Rails helpers: ```erb <%= sewing_kit_link_tag *sewing_kit_assets('main', extension: 'css') %> <%= sewing_kit_script_tag *sewing_kit_assets('main') %> ``` **Note:** CSS `` tags appear only in production; in development, CSS is embedded within the `main.js` bundle. ## Minimal Project Layout ``` ├── Gemfile (must contain "gem 'sewing_kit") ├── package.json (must specify '@shopify/sewing-kit' as a 'devDependency') │ └── app └── ui │ └─- index.js └── views └─- layouts └─- application.html.erb (must link to JS / CSS using sewing_kit_script_tag / sewing_kit_link_tag ``` ## Configuring development mode `SewingKit.configure` provides a `development_options` attribute that adjusts the behaviour of sewing-kit's development mode. See [the `dev` command's documentation](/docs/commands/dev.md) for a full list of options. ### Usage ```rb # config/initializers/sewing_kit.rb SewingKit.configure do |config| # Disable hot module reloading config.development_options[:hot] = false # Launch development mode with extra memory (helpful if source maps are # occupying more than Node's default 1.4GB heap allocation) config.development_options[:heap] = 4000 # Disable source maps (very large apps may need to builds sans source maps to # reduce development mode's memory usage) config.development_options[:source_maps] = 'off' end ``` ## Configuring production builds `SewingKit.configure` provides a `build_options` attribute that adjusts the behaviour of sewing-kit's build. See [the `build` command's documentation](/docs/commands/build.md#options) for a full list of options. ### Usage ```rb # config/initializers/sewing_kit.rb SewingKit.configure do |config| config.build_options = { # Disable type checks for faster, low memory builds (TypeScript only) # Note: you *must* have a separate `yarn sewing-kit type-check` CI step for this to be viable. type_check: false, # Increase heap to accommodate webpack's space for source map generation heap: 2000, # Overrides ShopifyCloud's configuration for the assets directory. # By default, when using the ShopifyCloud gem, assets are served from the CDN # - when `asset_directory` is not specified, it defaults to: `ShopifyCloud::AssetUploader.asset_directory` # - when specified, the asset path will be `https://cdn.shopify.com/shopifycloud/${assetDirectory}/bundles` # - lastly, set it to `false` to disable serving assets from the CDN altogether asset_directory: "foobar" } end ``` ## Testing the front end For fast tests with consistent results, test front-end components using Jest instead of Rails integration tests. Use [`sewing-kit test`](https://github.com/Shopify/sewing-kit/blob/main/docs/commands/test.md#L3) to run all `.test.tsx` files in the `app/ui` directory. [Jest](https://jestjs.io) is used as a test runner, with customization available via [its sewing-kit plugin](https://github.com/Shopify/sewing-kit/blob/main/docs/plugins/jest.md). ### Customizing the test environment Often you will want to hook up custom polyfills, global mocks, or other logic that needs to run either before the initialization of the test environment, or once for each test suite. By default, sewing-kit will look for such test setup files under `/app/ui/tests`. Check out the [documentation](https://github.com/Shopify/sewing-kit/blob/main/docs/plugins/jest.md#smart-defaults) for more details. ### Rails tests Building JavaScript assets for Rails tests adds friction to test driven development, but some projects rely on tests that intermingle erb / JavaScript behaviour. To accommodate different test styles, sewing_kit offers two test modes. #### `:return_no_assets` - sewing_kit helpers return empty arrays (default) As noted above, the Web Foundation team highly recommends `sewing-kit test` for front end testing. Projects following this recommendation can use sewing_kit's default behaviour for controller, integration tests, and e2e tests. Note that no sewing_kit content will appear in pages with this mode enabled. The default behaviour is equivalent to this configuration: ```rb # config/initializers/sewing_kit.rb SewingKit.configure do |config| config.test_manifest_mode = :return_no_assets end ``` #### Use precompiled assets If end-to-end tests are unavoidable: - Add extra steps to your test commands and CI pipelines that run `sewing-kit build --mode test` before test startup - Configure sewing_kit's `test_manifest_mode` to use precompiled assets: ```rb # config/initializers/sewing_kit.rb SewingKit.configure do |config| config.test_manifest_mode = :use_precompiled_assets end ``` If your tests require production assets, precompile using `sewing-kit build --mode production` instead. ## FAQ ### Which version of sewing-kit can I use? Assume that the sewing*kit gem's latest minor version requires \_at least* the same minor version of the sewing-kit package. If sewing-kit makes a breaking change, this gem's minor version will be bumped to match the required sewing-kit version. ### How can I fix production builds that are failing due to missing devDependencies? By moving everything into `package.json#dependencies`. This is necessary because Rails 5.2 prunes `devDependencies` during asset compilation. ### How can I test a production version of my changes? Ideally, by deploying to a `staging` environment. If that is not possible, a production-like local development experience is available via: ```sh NODE_ENV=production SK_SIMULATE_PRODUCTION=1 bundle exec rake assets:precompile NODE_ENV=production SK_SIMULATE_PRODUCTION=1 dev run ``` If your application includes a node server (eg. uses `quilt_rails`), you can run the node server in a separate terminal window with: `bin/rails sewing_kit:server:start` Note: - Code changes will not be automatically recompiled in this state - `SK_SIMULATE_PRODUCTION` does not make Rails itself run in production mode - The most accurate way to gauge performance of the production version of an application is via a `staging` environment After verifying production behaviour, run `bundle exec rake assets:clobber` to get back to development mode. ### My project is using `sprockets-commoner`, can I use sewing_kit too? No. sprockets-commoner uses an outdated Babel version, and is no longer compatible with sewing-kit. ## sewing-kit's logs are too noisy. How can I see less of them? sewing-kit defaults to using the same `log_level` as Rails' built in logger. It can be customized this using a configuration block: ```ruby SewingKit.configure do |config| config.log_level = :warn # may be `:inherit`, `:debug`, `:info`, `:warn`, or `:error` end ``` ### How do I run sewing-kit in debug mode? You can launch sewing-kit in debug mode by setting the `SK_DEBUG` environment flag. ```bash $ SK_DEBUG=1 dev run ``` This runs your rails app with the sewing-kit development server in debug mode. This is useful for when you want to debug sewing-kit from a rails app. Tip: Install the [Node.js V8 --inspector Manager (NiM)](https://chrome.google.com/webstore/detail/nodejs-v8-inspector-manag/gnhhdgbaldcilmgcpfddgdbkhjohddkj?hl=en) Chrome extension. This will launch a chrome debugger automatically for you.