minipack 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +46 -0
- data/LICENSE.txt +21 -0
- data/README.md +312 -0
- data/Rakefile +6 -0
- data/lib/minipack/command_runner.rb +59 -0
- data/lib/minipack/commands/base.rb +13 -0
- data/lib/minipack/commands/build.rb +33 -0
- data/lib/minipack/commands/pkg_install.rb +36 -0
- data/lib/minipack/configuration.rb +174 -0
- data/lib/minipack/file_change_watcher.rb +44 -0
- data/lib/minipack/helper.rb +103 -0
- data/lib/minipack/manifest.rb +86 -0
- data/lib/minipack/manifest_repository.rb +30 -0
- data/lib/minipack/railtie.rb +12 -0
- data/lib/minipack/rspec.rb +11 -0
- data/lib/minipack/version.rb +5 -0
- data/lib/minipack.rb +34 -0
- data/lib/webpack_manifest.rb +20 -0
- data/minipack.gemspec +32 -0
- metadata +134 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f8946e76b71b48eccb31e56408075341276eddbc8c1d8a3bc75a4c1969f7a327
|
4
|
+
data.tar.gz: 26418d01d9e406d37330eae60558ebe3b0a304d90c5fa312ab4b3b2924075193
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b3bbac2192c9098b951b16f5f48541b0aeb9a9fdd1aa16a26016fcd20c4fe02134e062277e474f0156348395966e56932d7503c0894a78aa38cf842e191b25e3
|
7
|
+
data.tar.gz: c7ea1f6a21823b101e91c11266819141824af89d819ea73bb63e9c52c0f8ca5c9406a7bfa880b255144dbd5cc4cfc2ccd24ffe5394869507de4c16341a15ee36
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# 0.3.0 / 2019-06-01
|
2
|
+
|
3
|
+
The project was renamed to Minipack from WebpackManifest since v0.3.0. Please refer to [the migration guide](docs/migrate_from_webpack_manifest.md') from WebpackManifest.
|
4
|
+
|
5
|
+
## Breaking changes
|
6
|
+
|
7
|
+
* Rename the project as Minipack.
|
8
|
+
|
9
|
+
## Enhancements:
|
10
|
+
|
11
|
+
* pre-build in test (#11)
|
12
|
+
* Enable to set default value through config_attr (#16)
|
13
|
+
|
14
|
+
# 0.2.4 / 2019-03-25
|
15
|
+
|
16
|
+
## Enhancements:
|
17
|
+
|
18
|
+
* Added `javascript_bundles_with_chunks_tag` and `stylesheet_bundles_with_chunks_tag` helpers, which creates html tags for a pack and all the dependent chunks, when using splitChunks. (#7)
|
19
|
+
|
20
|
+
# 0.2.3 / 2018-11-18
|
21
|
+
|
22
|
+
* Support passing symbols to helper methods (#5) by @jmortlock
|
23
|
+
|
24
|
+
# 0.2.2 / 2018-11-05
|
25
|
+
|
26
|
+
## Enhancements
|
27
|
+
|
28
|
+
* Support reading manifest.json from an uri (#4)
|
29
|
+
|
30
|
+
# 0.2.1 / 2018-10-18
|
31
|
+
|
32
|
+
* Improve exceptional case handling
|
33
|
+
|
34
|
+
# 0.2.0 / 2018-10-18
|
35
|
+
|
36
|
+
## Enhancements
|
37
|
+
|
38
|
+
* Multiple manifest files support
|
39
|
+
|
40
|
+
## Breaking changes
|
41
|
+
|
42
|
+
* Changed internal and public APIs
|
43
|
+
|
44
|
+
# 0.1.0 / 2018-10-17
|
45
|
+
|
46
|
+
Initial release
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Nobuhiro Nikushi
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,312 @@
|
|
1
|
+
# Minipack [![Build Status](https://travis-ci.org/nikushi/minipack.svg?branch=master)](https://travis-ci.org/nikushi/minipack) [![Gem Version](https://badge.fury.io/rb/minipack.svg)](https://badge.fury.io/rb/minipack)
|
2
|
+
|
3
|
+
Minipack, a gem for minimalists, which can integrates Rails with [webpack](https://webpack.js.org/). It is an alternative to [Webpacker](https://github.com/rails/).
|
4
|
+
|
5
|
+
Minipack provides view helpers through a manifest, which resolve paths of assets build by a webpack configured by you as you like.
|
6
|
+
|
7
|
+
**Note:** Before Minipack v0.3.0, it was called WebpackManifest. Please refer to [the migration guide](docs/migrate_from_webpack_manifest.md') from WebpackManifest.
|
8
|
+
|
9
|
+
## Features
|
10
|
+
|
11
|
+
* Rails view helpers to resolve paths to assets which are built by webpack according to a manifest file.
|
12
|
+
* Multiple manifest files support
|
13
|
+
* Pre-build assets before running tests
|
14
|
+
|
15
|
+
## Pre configuration
|
16
|
+
|
17
|
+
Unlike Webpacker, Minipack itself does not offer generating webpack configuration, DSL for setup, or scaffolding. So first you need to set up webpack in your favorite way.
|
18
|
+
|
19
|
+
Also, Minipack expects that webpack emits a manifest file. So please install [webpack-manifest-plugin](https://www.npmjs.com/package/webpack-manifest-plugin) and set it up accordingly.
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
Add this line to your application's Gemfile:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
gem 'minipack'
|
27
|
+
```
|
28
|
+
|
29
|
+
And then execute:
|
30
|
+
|
31
|
+
$ bundle
|
32
|
+
|
33
|
+
Or install it yourself as:
|
34
|
+
|
35
|
+
$ gem install minipack
|
36
|
+
|
37
|
+
## Configuration
|
38
|
+
|
39
|
+
After installed, configure your Rails app below as a new file `config/initializers/minipack.rb`.
|
40
|
+
|
41
|
+
```rb
|
42
|
+
Minipack.configuration do |c|
|
43
|
+
# By default c.cache is set to `false`, which means an application always parses a
|
44
|
+
# manifest.json. In development, you should set cache false usually.
|
45
|
+
# Instead, setting it `true` which caches the manifest in memory is recommended basically.
|
46
|
+
c.cache = !Rails.env.development?
|
47
|
+
|
48
|
+
# Register a path to a manifest file here. Right now you have to specify an absolute path.
|
49
|
+
c.manifest = Rails.root.join('public', 'assets', 'manifest.json')
|
50
|
+
|
51
|
+
# The base directory for the frontend system. By default, it will be
|
52
|
+
# `Rails.root`.
|
53
|
+
# c.base_path = Rails.root
|
54
|
+
#
|
55
|
+
# Suppose you want to change the root directory for the frontend system such as `frontend`.
|
56
|
+
# Note that a base_path can be a relative path from `Rails.root`.
|
57
|
+
# c.base_path = 'frontend'
|
58
|
+
|
59
|
+
# You can invokes a command to build assets in node from Minipack.
|
60
|
+
#
|
61
|
+
# When running tests, the lazy compilation is cached until a cache key, based
|
62
|
+
# on file checksum under your tracked paths, is changed. You can configure
|
63
|
+
# which paths are tracked by adding new paths to `build_cache_key`. Each path
|
64
|
+
# can be a relative path from the `base_dir`.
|
65
|
+
#
|
66
|
+
# The value will be as follows by default:
|
67
|
+
# c.build_cache_key = [
|
68
|
+
# 'package.json', 'package-lock.json', 'yarn.lock', 'webpack.config.js',
|
69
|
+
# 'webpackfile.js', 'config/webpack.config.js', 'config/webpackfile.js',
|
70
|
+
# 'app/javascripts/**/*',
|
71
|
+
# ]
|
72
|
+
#
|
73
|
+
# You can override it.
|
74
|
+
# c.build_cache_key = ['package.json', 'package-lock.json', 'config/webpack.config.js', 'src/**/*']
|
75
|
+
#
|
76
|
+
# Or you can add files in addition to the defaults:
|
77
|
+
# c.build_cache_key << 'src/**/*'
|
78
|
+
|
79
|
+
# A command to to build assets. The command you specify is executed under the `base_dir`.
|
80
|
+
# c.build_command = 'node_modules/.bin/webpack'
|
81
|
+
#
|
82
|
+
# You may want to customize it with options:
|
83
|
+
# c.build_command = 'node_modules/.bin/webpack --config config/webpack.config.js --mode production'
|
84
|
+
#
|
85
|
+
# You are also able to specify npm run script.
|
86
|
+
# c.build_command = 'npm run build'
|
87
|
+
|
88
|
+
# A full package installation command, with it's arguments and options. The command is executed under the `base_path`.
|
89
|
+
# c.pkg_install_command = 'npm install'
|
90
|
+
#
|
91
|
+
# If you prefer `yarn`:
|
92
|
+
# c.pkg_install_command = 'yarn install'
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
## Usage
|
97
|
+
|
98
|
+
### Rails view helpers
|
99
|
+
|
100
|
+
#### `asset_bundle_path`
|
101
|
+
|
102
|
+
This is a wrapper of [asset_path](https://api.rubyonrails.org/classes/ActionView/Helpers/AssetUrlHelper.html#method-i-asset_path). You can set any options of `asset_path`.
|
103
|
+
|
104
|
+
A given entry point name is resolved according to definition of manifest.
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
asset_bundle_path 'calendar.css'
|
108
|
+
# => "/assets/web/pack/calendar-1016838bab065ae1e122.css"
|
109
|
+
|
110
|
+
asset_bundle_path 'icon/favicon.ico'
|
111
|
+
# => "/assets/web/pack/icon/favicon-1016838bab065ae1e122.ico"
|
112
|
+
```
|
113
|
+
|
114
|
+
#### `javascript_bundle_tag`
|
115
|
+
|
116
|
+
This is a wrapper of [javascript_include_tag](https://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-javascript_include_tag). You can set any options of `javascript_include_tag`.
|
117
|
+
|
118
|
+
Given entry point name is resolved according to definition of manifest.
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
javascript_bundle_tag 'calendar', 'data-turbolinks-track': 'reload'
|
122
|
+
# => <script src="/assets/web/pack/calendar-1016838bab065ae1e314.js"
|
123
|
+
# data-turbolinks-track="reload"></script>
|
124
|
+
|
125
|
+
javascript_bundle_tag 'orders/app'
|
126
|
+
# => <script src="/assets/web/pack/orders/app-1016838bab065ae1e314.js"></script>
|
127
|
+
```
|
128
|
+
|
129
|
+
#### `stylesheet_bundle_tag`
|
130
|
+
|
131
|
+
This is a wrapper of [stylesheet_link_tag](https://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-stylesheet_link_tag). You can set any options of `stylesheet_link_tag`.
|
132
|
+
|
133
|
+
A given entry point name is resolved according to definition of manifest.
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
stylesheet_bundle_tag 'calendar', 'data-turbolinks-track': 'reload'
|
137
|
+
# => <link rel="stylesheet" media="screen"
|
138
|
+
# href="/assets/web/pack/calendar-1016838bab065ae1e122.css"
|
139
|
+
# data-turbolinks-track="reload" />
|
140
|
+
|
141
|
+
stylesheet_bundle_tag 'orders/style'
|
142
|
+
# => <link rel="stylesheet" media="screen"
|
143
|
+
# href="/assets/web/pack/orders/style-1016838bab065ae1e122.css" />
|
144
|
+
```
|
145
|
+
|
146
|
+
#### `image_bundle_tag`
|
147
|
+
|
148
|
+
This is a wrapper of [image_tag](https://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-image_tag). You can set any options of `image_tag`.
|
149
|
+
|
150
|
+
A given entry point name is resolved according to definition of manifest.
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
image_bundle_tag 'icon.png'
|
154
|
+
# => <img src="/assets/pack/icon-1016838bab065ae1e314.png" />
|
155
|
+
|
156
|
+
image_bundle_tag "icon.png", size: "16x10", alt: "Edit Entry"
|
157
|
+
# => <img src="/assets/pack/icon-1016838bab065ae1e314.png" width="16"
|
158
|
+
height="10" alt="Edit Entry" />
|
159
|
+
```
|
160
|
+
|
161
|
+
|
162
|
+
#### `javascript_bundles_with_chunks_tag` and `stylesheet_bundles_with_chunks_tag`
|
163
|
+
|
164
|
+
**Experimental** These are the helpers, which are similar to Webpacker, to support `splitChunks` feature introduced since Webpack 4.
|
165
|
+
|
166
|
+
For the full configuration options of splitChunks, see the Webpack's [documentation](https://webpack.js.org/plugins/split-chunks-plugin/).
|
167
|
+
|
168
|
+
Then use the `javascript_bundles_with_chunks_tag` and `stylesheet_bundles_with_chunks_tag` helpers to include all
|
169
|
+
the transpiled packs with the chunks in your view, which creates html tags for all the chunks.
|
170
|
+
|
171
|
+
```
|
172
|
+
<%= javascript_bundles_with_chunks_tag 'calendar', 'map', 'data-turbolinks-track': 'reload' %>
|
173
|
+
|
174
|
+
<!-- Creates the following: -->
|
175
|
+
<script src="/packs/vendor-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
|
176
|
+
<script src="/packs/calendar~runtime-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
|
177
|
+
<script src="/packs/calendar-1016838bab065ae1e314.js" data-turbolinks-track="reload"></script>
|
178
|
+
<script src="/packs/map~runtime-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
|
179
|
+
<script src="/packs/map-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
|
180
|
+
```
|
181
|
+
|
182
|
+
**Important:** Pass all your pack names to the helper otherwise you will get duplicated chunks on the page.
|
183
|
+
|
184
|
+
```
|
185
|
+
<%# DO %>
|
186
|
+
<%= javascript_bundles_with_chunks_tag 'calendar', 'map' %>
|
187
|
+
|
188
|
+
<%# DON'T %>
|
189
|
+
<%= javascript_bundles_with_chunks_tag 'calendar' %>
|
190
|
+
<%= javascript_bundles_with_chunks_tag 'map' %>
|
191
|
+
```
|
192
|
+
|
193
|
+
**Important:** Also, these helpers do not work with `webpack-manifest-plugin` npm because it has no support to generate a manifest with a set of of chunk entries https://github.com/danethurber/webpack-manifest-plugin/issues/133. Instead, [webpack-assets-manifest](https://github.com/webdeveric/webpack-assets-manifest) npm supports. Please change the plugin for manifest file generation if you wish to enable `splitChunks` feature.
|
194
|
+
|
195
|
+
```
|
196
|
+
const WebpackAssetsManifest = require('webpack-assets-manifest');
|
197
|
+
|
198
|
+
module.exports = {
|
199
|
+
// ...
|
200
|
+
plugins: [
|
201
|
+
new WebpackAssetsManifest({
|
202
|
+
entrypoints: true, // Please set this as true
|
203
|
+
})
|
204
|
+
],
|
205
|
+
// ...
|
206
|
+
}
|
207
|
+
```
|
208
|
+
|
209
|
+
## Advanced Configuration
|
210
|
+
|
211
|
+
### Hot Module Replacement in development
|
212
|
+
|
213
|
+
Optionally you can integrate the gem with [webpack-dev-server](https://github.com/webpack/webpack-dev-server) to enable live reloading by setting an manifest url served by webpack-dev-server, instead of a local file path. This should be used for development only.
|
214
|
+
|
215
|
+
Note that Minipack itself does not launches webpack-dev-server, so it must be started along with Rails server by yourself.
|
216
|
+
|
217
|
+
```rb
|
218
|
+
Minipack.configuration do |c|
|
219
|
+
c.cache = !Rails.env.development?
|
220
|
+
|
221
|
+
c.manifest = if Rails.env.development?
|
222
|
+
'http://localhost:8080/packs/manifest.json'
|
223
|
+
else
|
224
|
+
Rails.root.join('public', 'assets', 'manifest.json')
|
225
|
+
end
|
226
|
+
end
|
227
|
+
```
|
228
|
+
|
229
|
+
### Multiple manifest files support
|
230
|
+
|
231
|
+
This is optional. You can register multiple manifest files for the view helpers. This feature must be useful if your Rails project serves for several sites, then asset bundling process is isolated every site.
|
232
|
+
|
233
|
+
For example, your project serve for two sites, `shop` and `admin` from each individual manifest file. You can register each as
|
234
|
+
|
235
|
+
```rb
|
236
|
+
# In config/initializers/minipack.rb
|
237
|
+
|
238
|
+
Minipack.configuration do |c|
|
239
|
+
c.cache = !Rails.env.development?
|
240
|
+
|
241
|
+
# In order for Raild to handle multiple manifests, you must call `c.add` instead
|
242
|
+
# of `c.manifest=`. Note that the first registered one(e.g. `shop` in this
|
243
|
+
# example) is recognized as a default manifest.
|
244
|
+
c.add :shop do |co|
|
245
|
+
co.manifest = Rails.root.join('public', 'assets', 'manifest-shop.json')
|
246
|
+
co.base_path = Rails.root.join('frontend/shop')
|
247
|
+
end
|
248
|
+
|
249
|
+
c.add :admin do |co|
|
250
|
+
co.manifest = Rails.root.join('public', 'assets', 'manifest-admin.json')
|
251
|
+
co.base_path = Rails.root.join('frontend/admin')
|
252
|
+
# You can customize all configurable parameters per site.
|
253
|
+
co.build_cache_key << 'javascripts/**/*'
|
254
|
+
co.build_command = 'yarn install'
|
255
|
+
end
|
256
|
+
end
|
257
|
+
```
|
258
|
+
|
259
|
+
Then you can resolve a path with view helpers by passing `manifest:` option.
|
260
|
+
|
261
|
+
```
|
262
|
+
# This resolves a path by shop's manifest json.
|
263
|
+
javascript_bundle_tag('item_group_editor', manifest: :shop)
|
264
|
+
|
265
|
+
# This resolves a path by admin's manifest json.
|
266
|
+
asset_bundle_tag('favicon.ico', manifest: :admin)
|
267
|
+
|
268
|
+
# This resolves a path by shop's manifest json implicitly because the first one is marked as a default.
|
269
|
+
javascript_bundle_tag('item_group_editor')
|
270
|
+
```
|
271
|
+
|
272
|
+
## Building assets before running tests
|
273
|
+
|
274
|
+
To pre-build assets before runngin tests, add the following line (typically to your spec_helper.rb file):
|
275
|
+
|
276
|
+
```rb
|
277
|
+
require 'minipack/rspec'
|
278
|
+
```
|
279
|
+
|
280
|
+
## TODO
|
281
|
+
|
282
|
+
* Provides configuration generator for Rails initializers
|
283
|
+
|
284
|
+
## Acknowledgement
|
285
|
+
|
286
|
+
Special thanks to [@f_subal](https://twitter.com/f_subal) and his awesome blog [post](https://inside.pixiv.blog/subal/4615)(japanese).
|
287
|
+
|
288
|
+
## Alternatives
|
289
|
+
|
290
|
+
* [ed-mare/minipack_plugin](https://github.com/ed-mare/minipack_plugin)
|
291
|
+
|
292
|
+
## Development
|
293
|
+
|
294
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
295
|
+
|
296
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
297
|
+
|
298
|
+
**v0.3.x-trunk**
|
299
|
+
|
300
|
+
`v0.3.x-trunk` is the current active development branch. Please send pull requests to v0.3.x-trunk if you want any features.
|
301
|
+
|
302
|
+
**v0.2.x-trunk**
|
303
|
+
|
304
|
+
v0.2.x-trunk is made from the latest released version v0.2.4. I will not intend to actively maintain v0.2.x anymore, except security fixes or bug fixes.
|
305
|
+
|
306
|
+
## Contributing
|
307
|
+
|
308
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/nikushi/minipack.
|
309
|
+
|
310
|
+
## License
|
311
|
+
|
312
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'open3'
|
5
|
+
|
6
|
+
module Minipack
|
7
|
+
class CommandRunner
|
8
|
+
class UnsuccessfulError < StandardError; end
|
9
|
+
|
10
|
+
def initialize(env, command, chdir: '.', logger: nil, watcher: nil)
|
11
|
+
@env = env
|
12
|
+
@command = command
|
13
|
+
@chdir = chdir
|
14
|
+
@logger = logger || Logger.new(nil)
|
15
|
+
@watcher = watcher
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
run!
|
20
|
+
rescue UnsuccessfulError
|
21
|
+
false
|
22
|
+
end
|
23
|
+
|
24
|
+
def run!
|
25
|
+
@logger.info "Start executing #{@command}, within #{@chdir}"
|
26
|
+
|
27
|
+
return run_command if @watcher.nil?
|
28
|
+
|
29
|
+
if @watcher.stale?
|
30
|
+
run_command.tap do |success|
|
31
|
+
@watcher.record_digest if success
|
32
|
+
end
|
33
|
+
else
|
34
|
+
@logger.info 'Skipped because no file changes'
|
35
|
+
true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def run_command
|
42
|
+
stdout, stderr, status = Open3.capture3(
|
43
|
+
@env,
|
44
|
+
@command,
|
45
|
+
chdir: @chdir,
|
46
|
+
)
|
47
|
+
|
48
|
+
if status.success?
|
49
|
+
@logger.info "Executed successfully"
|
50
|
+
@logger.error "#{stderr}" unless stderr.empty?
|
51
|
+
else
|
52
|
+
@logger.error "Failed to execute:\n#{stderr}"
|
53
|
+
end
|
54
|
+
|
55
|
+
status.success? || raise(UnsuccessfulError, "Failed to execute #{@command}, exit:#{status.exitstatus}, stdout:#{stdout}, stderr:#{stderr}")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Minipack
|
4
|
+
module Commands
|
5
|
+
class Build < Base
|
6
|
+
def initialize(logger: nil)
|
7
|
+
@logger = logger
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
Minipack.configuration.leaves.each do |c|
|
12
|
+
# Note: someone wants pre_build hook?
|
13
|
+
build(c)
|
14
|
+
# Note: someone wants post_build hook?
|
15
|
+
end
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def build(c)
|
22
|
+
watcher = FileChangeWatcher.new(c.resolved_build_cache_key, File.join(c.cache_path, "last-build-digest-#{c.id}-#{::Rails.env}"))
|
23
|
+
CommandRunner.new(
|
24
|
+
{},
|
25
|
+
c.build_command,
|
26
|
+
chdir: c.resolved_base_path,
|
27
|
+
logger: @logger,
|
28
|
+
watcher: watcher,
|
29
|
+
).run!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Minipack
|
4
|
+
module Commands
|
5
|
+
class PkgInstall < Base
|
6
|
+
PKG_INSTALL_CACHE_KEY = ['package.json', 'package-lock.json', 'yarn.lock'].freeze
|
7
|
+
|
8
|
+
def initialize(logger: nil)
|
9
|
+
@logger = logger
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
Minipack.configuration.leaves.each do |c|
|
14
|
+
# Note: someone wants pre_pkg_install hook?
|
15
|
+
pkg_install(c)
|
16
|
+
# Note: someone wants post_pkg_install hook?
|
17
|
+
end
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def pkg_install(c)
|
24
|
+
pkg_install_cache_key = PKG_INSTALL_CACHE_KEY.map { |f| File.expand_path(f, c.resolved_base_path) }
|
25
|
+
watcher = FileChangeWatcher.new(pkg_install_cache_key, File.join(c.cache_path, "last-installation-digest-#{c.id}-#{::Rails.env}"))
|
26
|
+
CommandRunner.new(
|
27
|
+
{},
|
28
|
+
c.pkg_install_command,
|
29
|
+
chdir: c.resolved_base_path,
|
30
|
+
logger: @logger,
|
31
|
+
watcher: watcher,
|
32
|
+
).run!
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Minipack
|
4
|
+
# 1-level or 2-levels configuration system. With the typical single site usecase,
|
5
|
+
# only the root instance exists as a singleton. If you manage more then one site,
|
6
|
+
# each configuration is stored at the 2nd level of the configuration tree.
|
7
|
+
class Configuration
|
8
|
+
class Collection
|
9
|
+
include Enumerable
|
10
|
+
class NotFoundError < StandardError; end
|
11
|
+
|
12
|
+
def initialize(configs = [])
|
13
|
+
@configs = configs.map(&:id).zip(configs).to_h
|
14
|
+
end
|
15
|
+
|
16
|
+
def find(id)
|
17
|
+
@configs[id] || raise(NotFoundError, "collection not found by #{id}")
|
18
|
+
end
|
19
|
+
|
20
|
+
def each
|
21
|
+
@configs.values.each { |c| yield c }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Error < StandardError; end
|
26
|
+
|
27
|
+
ROOT_DEFAULT_ID = :''
|
28
|
+
BUILD_CACHE_KEY_DEFAULT = [
|
29
|
+
'package.json',
|
30
|
+
'package-lock.json',
|
31
|
+
'yarn.lock',
|
32
|
+
'webpack.config.js',
|
33
|
+
'webpackfile.js',
|
34
|
+
'config/webpack.config.js',
|
35
|
+
'config/webpackfile.js',
|
36
|
+
'app/javascripts/**/*',
|
37
|
+
].freeze
|
38
|
+
|
39
|
+
class << self
|
40
|
+
def config_attr(prop, default: nil)
|
41
|
+
define_method(prop) do
|
42
|
+
@config.fetch(prop) do
|
43
|
+
@parent ? @parent.public_send(prop) : default
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
define_method("#{prop}=".to_sym) do |v|
|
48
|
+
@config[prop] = v
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Private
|
54
|
+
config_attr :root_path
|
55
|
+
config_attr :id, default: ROOT_DEFAULT_ID
|
56
|
+
|
57
|
+
config_attr :cache, default: false
|
58
|
+
|
59
|
+
# The base directory of the frontend.
|
60
|
+
config_attr :base_path
|
61
|
+
|
62
|
+
config_attr :manifest
|
63
|
+
|
64
|
+
# The lazy compilation is cached until a file is change under the tracked paths.
|
65
|
+
config_attr :build_cache_key, default: BUILD_CACHE_KEY_DEFAULT.dup
|
66
|
+
|
67
|
+
# Let me leave this line for remember the indea of pre build hooks
|
68
|
+
# config_attr :pre_build_hooks, default: []
|
69
|
+
|
70
|
+
# The command for bundling assets
|
71
|
+
config_attr :build_command, default: 'node_modules/.bin/webpack'
|
72
|
+
|
73
|
+
# Let me leave this line to remember the indea of post build hooks
|
74
|
+
# config_attr :post_build_hooks, default: []
|
75
|
+
|
76
|
+
# Let me leave this line to remember the indea of pre pkg install hooks
|
77
|
+
# config_attr :pre_pkg_install_hooks, default: []
|
78
|
+
|
79
|
+
# The command for installation of npm packages
|
80
|
+
config_attr :pkg_install_command, default: 'npm install'
|
81
|
+
|
82
|
+
# Let me leave this line for remember the indea of post pkg install hooks
|
83
|
+
# config_attr :post_install_hooks, default: []
|
84
|
+
|
85
|
+
# Initializes a new instance of Configuration class.
|
86
|
+
#
|
87
|
+
# @param [Configuration,nil] parent refenrece to the parent configuration instance.
|
88
|
+
def initialize(parent = nil)
|
89
|
+
@parent = parent
|
90
|
+
# Only a root instance can have children, which are sub configurations each site.
|
91
|
+
@children = {}
|
92
|
+
@config = {}
|
93
|
+
end
|
94
|
+
|
95
|
+
# Register a sub configuration with a site name, with a manifest file
|
96
|
+
# optionally. You can configure per site.
|
97
|
+
#
|
98
|
+
# @param [Symbol] id uniq name of the site
|
99
|
+
# @param [String] path path of the manifest file
|
100
|
+
# @yieldparam [Configuration] config a sub configuration instance is sent to the block
|
101
|
+
def add(id, path = nil)
|
102
|
+
raise Error, 'Defining a sub configuration under a sub is not allowed' if leaf?
|
103
|
+
|
104
|
+
id = id.to_sym
|
105
|
+
config = self.class.new(self)
|
106
|
+
config.id = id
|
107
|
+
config.manifest = path unless path.nil?
|
108
|
+
|
109
|
+
# Link the root to the child
|
110
|
+
@children[id] = config
|
111
|
+
|
112
|
+
# The sub configuration can be configured within a block
|
113
|
+
yield config if block_given?
|
114
|
+
|
115
|
+
config
|
116
|
+
end
|
117
|
+
|
118
|
+
def children
|
119
|
+
Collection.new(@children.values)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Return scoped leaf nodes in self and children. This method is useful
|
123
|
+
# to get the concrete(enabled, or active) configuration instances.
|
124
|
+
# Each leaf inherit parameters from parent, so leaves always become
|
125
|
+
# active.
|
126
|
+
def leaves
|
127
|
+
col = @children.empty? ? [self] : @children.values
|
128
|
+
Collection.new(col)
|
129
|
+
end
|
130
|
+
|
131
|
+
# TODO: This will be moved to Minipack.manifests in the future.
|
132
|
+
def manifests
|
133
|
+
raise Error, 'Calling #manifests is only allowed from a root' unless root?
|
134
|
+
|
135
|
+
repo = ManifestRepository.new
|
136
|
+
# Determine if a single manifest mode or multiple manifests(multiple site) mode
|
137
|
+
targets = @children.empty? ? [self] : @children.values
|
138
|
+
targets.each do |config|
|
139
|
+
repo.add(config.id, config.manifest, cache: config.cache)
|
140
|
+
end
|
141
|
+
repo
|
142
|
+
end
|
143
|
+
|
144
|
+
# Resolve base_path as an absolute path
|
145
|
+
#
|
146
|
+
# @return [String]
|
147
|
+
def resolved_base_path
|
148
|
+
File.expand_path(base_path || '.', root_path)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Resolve build_cache_key as absolute paths
|
152
|
+
#
|
153
|
+
# @return [Array<String>]
|
154
|
+
def resolved_build_cache_key
|
155
|
+
base = resolved_base_path
|
156
|
+
build_cache_key.map { |path| File.expand_path(path, base) }
|
157
|
+
end
|
158
|
+
|
159
|
+
# @return [String]
|
160
|
+
def cache_path
|
161
|
+
File.join(root_path, 'tmp', 'cache', 'minipack')
|
162
|
+
end
|
163
|
+
|
164
|
+
private
|
165
|
+
|
166
|
+
def root?
|
167
|
+
@parent.nil?
|
168
|
+
end
|
169
|
+
|
170
|
+
def leaf?
|
171
|
+
!root?
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "digest/sha1"
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module Minipack
|
7
|
+
class FileChangeWatcher
|
8
|
+
# @param [Array<Pathname>] watched_paths
|
9
|
+
# @param [Pathname] digest_store_path
|
10
|
+
def initialize(watched_paths, digest_store_path)
|
11
|
+
@watched_paths = watched_paths
|
12
|
+
@digest_store_path = Pathname.new(digest_store_path)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns true if all watched files are up to date
|
16
|
+
def fresh?
|
17
|
+
watched_files_digest == last_stored_digest
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns true if the watched files are out of date
|
21
|
+
def stale?
|
22
|
+
!fresh?
|
23
|
+
end
|
24
|
+
|
25
|
+
def record_digest
|
26
|
+
@digest_store_path.dirname.mkpath
|
27
|
+
@digest_store_path.write(watched_files_digest)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def last_stored_digest
|
33
|
+
@digest_store_path.read if @digest_store_path.exist?
|
34
|
+
rescue Errno::ENOENT, Errno::ENOTDIR
|
35
|
+
end
|
36
|
+
|
37
|
+
def watched_files_digest
|
38
|
+
files = Dir[*@watched_paths].reject { |f| File.directory?(f) }
|
39
|
+
file_ids = files.sort.map { |f| "#{File.basename(f)}/#{Digest::SHA1.file(f).hexdigest}" }
|
40
|
+
Digest::SHA1.hexdigest(file_ids.join("/"))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'action_view'
|
4
|
+
|
5
|
+
module Minipack::Helper
|
6
|
+
# Example:
|
7
|
+
#
|
8
|
+
# <%= asset_bundle_path 'calendar.css' %> # => "/assets/web/pack/calendar-1016838bab065ae1e122.css"
|
9
|
+
# <%= asset_bundle_path 'icon/favicon.ico' %> # => "/assets/web/pack/icon/favicon-1016838bab065ae1e122.ico"
|
10
|
+
def asset_bundle_path(name, manifest: nil, **options)
|
11
|
+
manifest = get_manifest_by_key(manifest)
|
12
|
+
asset_path(manifest.lookup!(name.to_s), **options)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Example:
|
16
|
+
#
|
17
|
+
# <%= javascript_bundle_tag 'calendar', 'data-turbolinks-track': 'reload' %> # =>
|
18
|
+
# <script src="/assets/web/pack/calendar-1016838bab065ae1e314.js" data-turbolinks-track="reload"></script>
|
19
|
+
#
|
20
|
+
# <%= javascript_bundle_tag 'orders/app' %> # =>
|
21
|
+
# <script src="/assets/web/pack/orders/app-1016838bab065ae1e314.js"></script>
|
22
|
+
def javascript_bundle_tag(*names, manifest: nil, **options)
|
23
|
+
javascript_include_tag(*sources_from_manifest(names, 'js', key: manifest), **options)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Creates script tags that references the js chunks from entrypoints when using split chunks API.
|
27
|
+
# See: https://webpack.js.org/plugins/split-chunks-plugin/
|
28
|
+
# Example:
|
29
|
+
#
|
30
|
+
# <%= javascript_bundles_with_chunks_tag 'calendar', 'map', 'data-turbolinks-track': 'reload' %> # =>
|
31
|
+
# <script src="/packs/vendor-16838bab065ae1e314.chunk.js" data-turbolinks-track="reload"></script>
|
32
|
+
# <script src="/packs/calendar~runtime-16838bab065ae1e314.chunk.js" data-turbolinks-track="reload"></script>
|
33
|
+
# <script src="/packs/calendar-1016838bab065ae1e314.chunk.js" data-turbolinks-track="reload"></script>
|
34
|
+
# <script src="/packs/map~runtime-16838bab065ae1e314.chunk.js" data-turbolinks-track="reload"></script>
|
35
|
+
# <script src="/packs/map-16838bab065ae1e314.chunk.js" data-turbolinks-track="reload"></script>
|
36
|
+
# DO:
|
37
|
+
# <%= javascript_bundles_with_chunks_tag 'calendar', 'map' %>
|
38
|
+
# DON'T:
|
39
|
+
# <%= javascript_bundles_with_chunks_tag 'calendar' %>
|
40
|
+
# <%= javascript_bundles_with_chunks_tag 'map' %>
|
41
|
+
def javascript_bundles_with_chunks_tag(*names, manifest: nil, **options)
|
42
|
+
javascript_include_tag(*sources_from_manifest_entrypoints(names, 'js', key: manifest), **options)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Examples:
|
46
|
+
#
|
47
|
+
# <%= stylesheet_bundle_tag 'calendar', 'data-turbolinks-track': 'reload' %> # =>
|
48
|
+
# <link rel="stylesheet" media="screen"
|
49
|
+
# href="/assets/web/pack/calendar-1016838bab065ae1e122.css" data-turbolinks-track="reload" />
|
50
|
+
#
|
51
|
+
# <%= stylesheet_bundle_tag 'orders/style' %> # =>
|
52
|
+
# <link rel="stylesheet" media="screen"
|
53
|
+
# href="/assets/web/pack/orders/style-1016838bab065ae1e122.css" />
|
54
|
+
def stylesheet_bundle_tag(*names, manifest: nil, **options)
|
55
|
+
stylesheet_link_tag(*sources_from_manifest(names, 'css', key: manifest), **options)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Creates link tags that references the css chunks from entrypoints when using split chunks API.
|
59
|
+
# See: https://webpack.js.org/plugins/split-chunks-plugin/
|
60
|
+
# Example:
|
61
|
+
#
|
62
|
+
# <%= stylesheet_bundles_with_chunks_tag 'calendar', 'map' %> # =>
|
63
|
+
# <link rel="stylesheet" media="screen" href="/packs/3-8c7ce31a.chunk.css" />
|
64
|
+
# <link rel="stylesheet" media="screen" href="/packs/calendar-8c7ce31a.chunk.css" />
|
65
|
+
# <link rel="stylesheet" media="screen" href="/packs/map-8c7ce31a.chunk.css" />
|
66
|
+
# DO:
|
67
|
+
# <%= stylesheet_bundles_with_chunks_tag 'calendar', 'map' %>
|
68
|
+
# DON'T:
|
69
|
+
# <%= stylesheet_bundles_with_chunks_tag 'calendar' %>
|
70
|
+
# <%= stylesheet_bundles_with_chunks_tag 'map' %>
|
71
|
+
def stylesheet_bundles_with_chunks_tag(*names, manifest: nil, **options)
|
72
|
+
stylesheet_link_tag(*sources_from_manifest_entrypoints(names, 'css', key: manifest), **options)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Examples:
|
76
|
+
#
|
77
|
+
# <%= image_bundle_tag 'icon.png'
|
78
|
+
# <img src="/assets/pack/icon-1016838bab065ae1e314.png" />
|
79
|
+
#
|
80
|
+
# <%= image_bundle_tag "icon.png", size: "16x10", alt: "Edit Entry"
|
81
|
+
# <img src="/assets/pack/icon-1016838bab065ae1e314.png" width="16" height="10" alt="Edit Entry" />
|
82
|
+
def image_bundle_tag(name, manifest: nil, **options)
|
83
|
+
manifest = get_manifest_by_key(manifest)
|
84
|
+
image_tag(manifest.lookup!(name.to_s), **options)
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def sources_from_manifest(names, ext, key: nil)
|
90
|
+
manifest = get_manifest_by_key(key)
|
91
|
+
names.map { |name| manifest.lookup!(name.to_s + '.' + ext) }
|
92
|
+
end
|
93
|
+
|
94
|
+
def sources_from_manifest_entrypoints(names, type, key: nil)
|
95
|
+
manifest = get_manifest_by_key(key)
|
96
|
+
names.map { |name| manifest.lookup_pack_with_chunks!(name, type: type) }.flatten.uniq
|
97
|
+
end
|
98
|
+
|
99
|
+
def get_manifest_by_key(key = nil)
|
100
|
+
repository = Minipack.configuration.manifests
|
101
|
+
key.nil? ? repository.default : repository.get(key)
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'open-uri'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
module Minipack
|
8
|
+
class Manifest
|
9
|
+
class MissingEntryError < StandardError; end
|
10
|
+
class FileNotFoundError < StandardError; end
|
11
|
+
|
12
|
+
attr_reader :path
|
13
|
+
attr_writer :cache
|
14
|
+
|
15
|
+
def initialize(path, cache: false)
|
16
|
+
@path = path.to_s
|
17
|
+
@cache = cache
|
18
|
+
end
|
19
|
+
|
20
|
+
def lookup_pack_with_chunks!(name, type: nil)
|
21
|
+
manifest_pack_type = manifest_type(name, type)
|
22
|
+
manifest_pack_name = manifest_name(name, manifest_pack_type)
|
23
|
+
find('entrypoints')&.dig(manifest_pack_name, manifest_pack_type) || handle_missing_entry(name)
|
24
|
+
end
|
25
|
+
|
26
|
+
def lookup!(name)
|
27
|
+
find(name) || handle_missing_entry(name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def find(name)
|
31
|
+
data[name.to_s]
|
32
|
+
end
|
33
|
+
|
34
|
+
def assets
|
35
|
+
data.values
|
36
|
+
end
|
37
|
+
|
38
|
+
def cache_enabled?
|
39
|
+
@cache
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def data
|
45
|
+
if cache_enabled?
|
46
|
+
@data ||= load_data
|
47
|
+
else
|
48
|
+
load_data
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def load_data
|
53
|
+
u = URI.parse(@path)
|
54
|
+
data = nil
|
55
|
+
if u.scheme == 'file' || u.path == @path # file path
|
56
|
+
raise(FileNotFoundError, "#{@path}: no such manifest found") unless File.exist?(@path)
|
57
|
+
data = File.read(@path)
|
58
|
+
else
|
59
|
+
# http url
|
60
|
+
data = u.read
|
61
|
+
end
|
62
|
+
JSON.parse(data)
|
63
|
+
end
|
64
|
+
|
65
|
+
# The `manifest_name` method strips of the file extension of the name, because in the
|
66
|
+
# manifest hash the entrypoints are defined by their pack name without the extension.
|
67
|
+
# When the user provides a name with a file extension, we want to try to strip it off.
|
68
|
+
def manifest_name(name, pack_type)
|
69
|
+
return name if File.extname(name.to_s).empty?
|
70
|
+
File.basename(name, '.' + pack_type)
|
71
|
+
end
|
72
|
+
|
73
|
+
def manifest_type(name, pack_type)
|
74
|
+
return File.extname(name)[1..-1] if pack_type.nil?
|
75
|
+
pack_type.to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
def handle_missing_entry(name)
|
79
|
+
raise MissingEntryError, <<~MSG
|
80
|
+
Can not find #{name} in #{@path}.
|
81
|
+
Your manifest contains:
|
82
|
+
#{JSON.pretty_generate(@data)}
|
83
|
+
MSG
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Minipack
|
4
|
+
class ManifestRepository
|
5
|
+
class NotFoundError < StandardError; end
|
6
|
+
|
7
|
+
attr_accessor :default
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@manifests = {}
|
11
|
+
@default = nil # a pointer to a default manifest
|
12
|
+
end
|
13
|
+
|
14
|
+
def all_manifests
|
15
|
+
@manifests.values
|
16
|
+
end
|
17
|
+
|
18
|
+
# @private
|
19
|
+
def add(key, path, **options)
|
20
|
+
manifest = Minipack::Manifest.new(path, options)
|
21
|
+
# Mark a first one as a default
|
22
|
+
@default = manifest if @manifests.empty?
|
23
|
+
@manifests[key.to_sym] = manifest
|
24
|
+
end
|
25
|
+
|
26
|
+
def get(key)
|
27
|
+
@manifests[key.to_sym] || raise(NotFoundError, "manifest associated with #{key} not found")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails'
|
4
|
+
|
5
|
+
module Minipack
|
6
|
+
class Railtie < ::Rails::Railtie
|
7
|
+
initializer "minipack.set_defaults" do
|
8
|
+
Minipack.configuration.root_path = ::Rails.root.to_s
|
9
|
+
Minipack.configuration.base_path = ::Rails.root.to_s
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.configure do |c|
|
4
|
+
c.before :suite do
|
5
|
+
logger = Logger.new(STDOUT).tap do |l|
|
6
|
+
l.formatter = proc { |severity, datetime, progname, msg| "#{msg}\n" }
|
7
|
+
end
|
8
|
+
Minipack::Commands::PkgInstall.call(logger: logger)
|
9
|
+
Minipack::Commands::Build.call(logger: logger)
|
10
|
+
end
|
11
|
+
end
|
data/lib/minipack.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module Minipack
|
6
|
+
require 'minipack/manifest'
|
7
|
+
require 'minipack/configuration'
|
8
|
+
require 'minipack/helper'
|
9
|
+
require 'minipack/manifest_repository'
|
10
|
+
require 'minipack/file_change_watcher'
|
11
|
+
require 'minipack/command_runner'
|
12
|
+
require 'minipack/railtie'
|
13
|
+
require 'minipack/commands/base'
|
14
|
+
require 'minipack/commands/build'
|
15
|
+
require 'minipack/commands/pkg_install'
|
16
|
+
require "minipack/version"
|
17
|
+
|
18
|
+
class << self
|
19
|
+
def configuration(&block)
|
20
|
+
@configuration ||= Configuration.new
|
21
|
+
yield @configuration if block_given?
|
22
|
+
@configuration
|
23
|
+
end
|
24
|
+
attr_writer :configuration
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'active_support/lazy_load_hooks'
|
29
|
+
ActiveSupport.on_load :action_view do
|
30
|
+
::ActionView::Base.send :include, Minipack::Helper
|
31
|
+
end
|
32
|
+
|
33
|
+
# To keep backward compatibility
|
34
|
+
require_relative 'webpack_manifest'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @deprecated Use Minipack instead
|
4
|
+
module WebpackManifest
|
5
|
+
module Rails
|
6
|
+
class << self
|
7
|
+
# @deprecated Use Minipack.configuration API instead
|
8
|
+
def configuration(&block)
|
9
|
+
ActiveSupport::Deprecation.warn('WebpackManifest::Rails.configuration was deprecated. Use Minipack.configuration instead.')
|
10
|
+
Minipack.configuration(&block)
|
11
|
+
end
|
12
|
+
|
13
|
+
# @deprecated Use Minipack.configuration= API instead
|
14
|
+
def configuration=(c)
|
15
|
+
ActiveSupport::Deprecation.warn('WebpackManifest::Rails.configuration= was deprecated. Use Minipack.configuration= instead.')
|
16
|
+
Minipack.configuration = c
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/minipack.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "minipack/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "minipack"
|
8
|
+
spec.version = Minipack::VERSION
|
9
|
+
spec.authors = ["Nobuhiro Nikushi"]
|
10
|
+
spec.email = ["deneb.ge@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = "Minipack is a gem for minimalists that integrates Rails and webpack without Webpcker"
|
13
|
+
spec.description = spec.summary
|
14
|
+
spec.homepage = "https://github.com/nikushi/minipack"
|
15
|
+
spec.license = "MIT"
|
16
|
+
spec.files = Dir['lib/**/*.rb'] + %w[
|
17
|
+
CHANGELOG.md
|
18
|
+
LICENSE.txt
|
19
|
+
README.md
|
20
|
+
Rakefile
|
21
|
+
minipack.gemspec
|
22
|
+
]
|
23
|
+
spec.require_paths = ['lib']
|
24
|
+
|
25
|
+
spec.required_ruby_version = '>= 2.0.0'
|
26
|
+
|
27
|
+
spec.add_dependency 'actionview'
|
28
|
+
spec.add_dependency "railties", ">= 4.2"
|
29
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
30
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: minipack
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nobuhiro Nikushi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-06-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: actionview
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: railties
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '4.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
description: Minipack is a gem for minimalists that integrates Rails and webpack without
|
84
|
+
Webpcker
|
85
|
+
email:
|
86
|
+
- deneb.ge@gmail.com
|
87
|
+
executables: []
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- CHANGELOG.md
|
92
|
+
- LICENSE.txt
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- lib/minipack.rb
|
96
|
+
- lib/minipack/command_runner.rb
|
97
|
+
- lib/minipack/commands/base.rb
|
98
|
+
- lib/minipack/commands/build.rb
|
99
|
+
- lib/minipack/commands/pkg_install.rb
|
100
|
+
- lib/minipack/configuration.rb
|
101
|
+
- lib/minipack/file_change_watcher.rb
|
102
|
+
- lib/minipack/helper.rb
|
103
|
+
- lib/minipack/manifest.rb
|
104
|
+
- lib/minipack/manifest_repository.rb
|
105
|
+
- lib/minipack/railtie.rb
|
106
|
+
- lib/minipack/rspec.rb
|
107
|
+
- lib/minipack/version.rb
|
108
|
+
- lib/webpack_manifest.rb
|
109
|
+
- minipack.gemspec
|
110
|
+
homepage: https://github.com/nikushi/minipack
|
111
|
+
licenses:
|
112
|
+
- MIT
|
113
|
+
metadata: {}
|
114
|
+
post_install_message:
|
115
|
+
rdoc_options: []
|
116
|
+
require_paths:
|
117
|
+
- lib
|
118
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 2.0.0
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
requirements: []
|
129
|
+
rubygems_version: 3.0.3
|
130
|
+
signing_key:
|
131
|
+
specification_version: 4
|
132
|
+
summary: Minipack is a gem for minimalists that integrates Rails and webpack without
|
133
|
+
Webpcker
|
134
|
+
test_files: []
|