Skip to content

Instantly share code, notes, and snippets.

@rmacklin
Last active May 19, 2019 20:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rmacklin/8e60e6d68162dc3530533a575f4b9fbe to your computer and use it in GitHub Desktop.
Save rmacklin/8e60e6d68162dc3530533a575f4b9fbe to your computer and use it in GitHub Desktop.
# config/initializers/assets.rb
module ExternalAssetPipeline
class AssetNotFound < StandardError; end
mattr_accessor :manifest
class Manifest
def find(name)
data[name.to_s].presence
end
private
def data
if Rails.application.config.cache_revisioned_asset_manifest
@data ||= load
else
load
end
end
def load
manifest_file_path = Rails.root.join('public', 'packs', '.revisioned-asset-manifest.json')
JSON.parse(manifest_file_path.read)
end
end
# Overrides the built-in `ActionView::Helpers::AssetUrlHelper#compute_asset_path` to use the
# external asset pipeline, in the same manner that sprockets-rails does:
# https://github.com/rails/sprockets-rails/blob/v3.2.1/lib/sprockets/rails/helper.rb#L74-L96
def compute_asset_path(source, _options = {})
value_in_asset_manifest = ExternalAssetPipeline.manifest.find(source)
return "/packs/#{value_in_asset_manifest}" if value_in_asset_manifest
raise AssetNotFound,
"The asset #{source.inspect} is not present in the asset manifest"
end
end
ExternalAssetPipeline.manifest = ExternalAssetPipeline::Manifest.new
ActionView::Base.include ExternalAssetPipeline
const glob = require('glob');
const path = require('path');
const util = require('util');
const WebpackAssetsManifest = require('webpack-assets-manifest');
const entryDir = 'packs';
const sourceRoot = path.resolve(__dirname, './app/javascript');
const entryRoot = path.resolve(sourceRoot, entryDir);
const targetRoot = path.resolve(__dirname, `./public/${entryDir}`);
const extensions = ['js', 'jsx', 'ts', 'tsx'];
const mode = process.env.NODE_ENV || 'development';
const config = {
context: entryRoot,
entry: async () => {
const globPromise = util.promisify(glob);
const paths = await globPromise(`${entryRoot}/**/*.{${extensions.join(',')}}`);
const entry = {};
paths.forEach((p) => {
const relativePath = path.relative(entryRoot, p);
const parts = path.parse(relativePath);
const chunkName = path.join(parts.dir, parts.name);
entry[chunkName] = p;
});
return entry;
},
mode,
module: {
rules: [
{
include: [sourceRoot],
test: /\.(t|j)sx?$/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
},
},
},
]
},
node: false,
output: {
filename: '[name]-[hash].js',
path: targetRoot
},
plugins: [
new WebpackAssetsManifest({
merge: true,
output: '.revisioned-asset-manifest.json',
}),
],
resolve: {
extensions: extensions.map(e => `.${e}`)
}
};
if (mode === 'development') {
config.devtool = 'cheap-source-map';
}
module.exports = config;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment