Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/rupurt/webpack-sprockets-rails-manifest-plugin

Allow Sprockets to load files from a Webpack build
https://github.com/rupurt/webpack-sprockets-rails-manifest-plugin

Last synced: 4 days ago
JSON representation

Allow Sprockets to load files from a Webpack build

Awesome Lists containing this project

README

        

Webpack Sprockets Rails Manifest Plugin
=======================================

A Webpack plugin that allows [`sprockets-rails`](https://github.com/rails/sprockets-rails)
to find static assets from a Webpack build without requiring them in sprockets directives.
We can leverage standard Rails view helpers (i.e. `javascript_include_tag`, `stylesheet_link_tag`)
to load artifacts supporting finger printing and prepended host urls.

## Rails Gem

To automatically create the recommended configuration install the [`webpack_on_rails`](https://github.com/rupurt/webpack-sprockets-rails-manifest-plugin)
gem and run the `webpack_on_rails:install` generator.

## Manual Install

### yarn

```bash
yarn add webpack-sprockets-rails-manifest-plugin
```

### npm

```bash
npm install webpack-sprockets-rails-manifest-plugin --save
```

## Usage

```ruby
# config/initializers/assets.rb
# Avoid creating the manifest file in public/assets as it can be downloaded by anyone
Rails.configuration.assets.manifest = Rails.root.join("config", "sprockets-manifest.json")
```

```ruby
# config/environments/development.rb
config.assets.debug = false
```

```erb
<% # app/views/layouts/application.html.erb %>
<% # Use rails helpers in the same way you normally would with sprockets %>



<%= javascript_include_tag "webpack-application-bundle" %>

```

```javascript
// client/bundles/webpack-application.js
alert("Howdy, Webpack is working!");
```

```javascript
// client/webpack.config.js
var path = require("path");
var WebpackSprocketsRailsManifestPlugin = require("webpack-sprockets-rails-manifest-plugin");

var config = {
context: __dirname,

entry: {
"webpack-application-bundle": "./bundles/webpack-application"
},

output: {
path: path.resolve(__dirname, "../public/assets"),
filename: "[name]-[chunkhash].js"
},

// Other config ...

plugins: [
new WebpackSprocketsRailsManifestPlugin({
// [optional] this is the default location relative to the output directory
// that the assets will be built. e.g `public/assets`
manifestFile: "../../config/sprockets-manifest.json"
})
]
};

module.exports = config;
```

## Heroku

Follow the [instructions](https://devcenter.heroku.com/articles/nodejs-support)
to install the ruby and node multi-buildpack.

Create a `package.json` file in the root of the rails project.

```json
{
"name": "MyProject",
"version": "1.0.0",
"description": "A description of MyProject",
"main": "index.js",
"cacheDirectories": [
"client/node_modules"
],
"scripts": {
"preinstall": "cd client && npm install",
"postinstall": "cd client && npm run build"
}
}
```

## Hot Module Replacement

Rails provides us with the ability prepend a host to our asset paths generated by
the Rails view helpers. This option is normally configured for production environments
but we can use it in development to load assets from `webpack-dev-server` instead of
public.

```sh
export ASSET_HOST=http://localhost:8080
```

```ruby
# config/application.rb
# ...

if ENV["ASSET_HOST"].present?
Rails.application.config.action_controller.asset_host = proc { |source, _request|
ENV["ASSET_HOST"]
}
end
```

## Gradually Replacing the Asset Pipeline with Webpack

The Webpack ecosystem works best when it controls a whole subpath. For greenfield
projects this is easy to achieve. However if you're running a legacy Rails app, don't
fret! Webpack can copy build files into a location so that they can be required via
sprockets directives. We recommend using this technique when you're just getting started,
but the end goal should be to have Webpack completely control the build process
of your static assets. For more information and setup instructions check out the
separate plugin [`webpack-copy-after-build-plugin`](https://github.com/rupurt/webpack-copy-after-build-plugin).

## How Does It Work?

`sprockets-rails` provides two strategies to map logical paths (`webpack-application.js`)
to file system paths (`webpack-application-8f88619b6ef3a358a7ad.js`). By using the
`manifest` strategy we can load finger printed static assets via the existing
view helpers (i.e. `javascript_include_tag`, `stylesheet_link_tag`).

#### Environment

Searches the default sprockets directory for a file type manifest. By default
this is only enabled in the `dev` and `test` environments e.g.

```javascript
// app/assets/javascripts/application.js
//= require_self
alert("Hi, I'm a Javascript manifest in the default Sprockets Asset Pipeline");
```

#### Manifest

A json file which stores a mapping between a compiled asset and the original
logical path, along with meta information such as size, creation time and
integrity hash. `webpack-sprockets-rails-manifest-plugin` uses this manifest file
to make `sprockets-rails` aware of the files and meta information in the
`webpack` build. Since Rails 3.x `sprockets-rails` writes it's manifest file to
a dynamic location using a randomly generated filename (e.g. `public/assets/.sprockets-manifest-b4b2e3829c91f2f867c051a855232bed.json`).
To get `sprockets-rails` and `webpack` talking to each other we need to
configure `sprockets-rails` to write it's manifest file to a static location
that `webpack` knows about.

If `Rails.configuration.assets.debug = false` the asset pipeline will check the
manifest first, if an entry can't be found, it falls back and checks the file
system through the environment strategy.

## Examples

Head over to [https://github.com/rupurt/react_on_rails_simplified_configuration_examples](https://github.com/rupurt/react_on_rails_simplified_configuration_examples)
for examples on how to configure:

* Greenfield Rails projects
* Legacy Rails projects
* Hot Module Replacement

## TODO
* [x] - support webpack-dev-server
* [x] - gradual migration documentation
* [x] - sample projects
* [x] - Rails gem
* [ ] - tests
* [ ] - [`script` integrity](https://w3c.github.io/webappsec-subresource-integrity)

## License

[MIT](https://opensource.org/licenses/MIT)