opal-webpack-loader 0.11.4 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e7e5f3b220d06e291ef7a5805237d73c53b27313766b7891e0bc18a8b00ccc8
4
- data.tar.gz: 5d1078190a7c4b286de96c8114e9692728b87f6063c558c7de5737e3513f4b0d
3
+ metadata.gz: cd885fbcf9cc014f09d6f42a31ad1d0b815b17d587d33808156ec79579255f86
4
+ data.tar.gz: 2558ff9c76e5a07d98b6f0a94f829dcd51460197ef7176ff25fed2f742af2c31
5
5
  SHA512:
6
- metadata.gz: e4bd10876231791a4a9368212950c81e1b8f007daa895db6ae95d0c01571a3ea3672650e35bda7765c74b06e02000a1164deb264dc22980e413d290bae9cc3e4
7
- data.tar.gz: 70ba5421ca317f15126577d6990d30d9b354ee1c6864b28518756d07d99b9df13a25912331fe67a8e6034a1d4f9fc40da5e8941cc2aa7402d21b5f540bedfefd
6
+ metadata.gz: '07961ad0a9c60e9de83f6caedb60c1038bd721e898b52a8eaf5e8b118b268baba5d4527764d500a1e6a8bacb2ae88543896a959fd45245e61f331dbf21809f6c'
7
+ data.tar.gz: 7ecd145ff65cee4b2c5f9b59a5f096736356e0283f8548ae7743bcd845e2d0400df5ed0dd8087166269622aeadf58cf1c06da8f555d52954338f0c0b1c918bb0
data/README.md CHANGED
@@ -1,216 +1,212 @@
1
- <h1 align="center">
2
- <img src="https://raw.githubusercontent.com/isomorfeus/opal-webpack-loader/master/docs/owl.png"
3
- align="center" title="Opal logo by Elia Schito combined with Webpack Logo" width="111" height="125" />
4
- <br/>
5
- opal-webpack-loader<br/>
6
- <img src="https://img.shields.io/badge/Opal-Ruby%20💛%20JavaScript%20💛%20Webpack-yellow.svg?logo=ruby&style=social&logoColor=777"/>
7
- </h1>
8
-
9
- Bundle assets with webpack, resolve and compile opal ruby files and import them in the bundle, without sprockets or the webpacker gem
10
- (but can be used with both of them too).
11
- Includes a loader and resolver plugin for webpack.
12
-
13
- ### Community and Support
14
- At the [Isomorfeus Framework Project](http://isomorfeus.com)
15
-
16
- ### Tested
17
- [TravisCI](https://travis-ci.org): [![Build Status](https://travis-ci.org/isomorfeus/opal-webpack-loader.svg?branch=master)](https://travis-ci.org/isomorfeus/opal-webpack-loader)
18
-
19
- ### Features
20
- - comes with a installer for rails and other frameworks
21
- - webpack based build process
22
- - very fast, asynchronous and parallel builds of opal code:
23
- opal-webpack-loader-0.7.1 compiles all of opal, a bunch of gems and over 19000SLC on a
24
- Intel® Core™ i7-7700HQ CPU @ 2.80GHz × 8, with 8 workers in around 1850ms
25
- - support for memcached or redis as compiler cache
26
- - fast builds on windows too, parallel when building multiple assets with parallel-webpack
27
- - opal modules are packaged as es6 modules
28
- - support for rails with webpacker
29
- - other webpack features become available, like:
30
- - source maps
31
- - multiple targets: web (for browsers), node (for server side rendering) and webworker (for Web Workers)
32
- - hot module reloading for opal ruby code and stylesheets and html views
33
- - tree shaking
34
- - code splitting
35
- - lazy loading
36
- - everything else webpack can do, like loading stylesheets, etc.
37
-
38
- ### Requirements
39
- - npm or yarn
40
- - opal-webpack-loader consists of 2 parts, the npm package and the gem, both are required and must be the same version.
41
- - webpack ^4.46
42
- - webpack-dev-server ^3.11.0
43
- - one of the ES6 modules branches of opal
44
- - [PR#1973](https://github.com/opal/opal/pull/1973), (experimental) implementing ES6 modules and changes for 'strict' mode,
45
- based on Opal master 1.0.0 using javascript string objects "mutable strings" by default for all strings
46
-
47
- `gem 'opal', github: 'janbiedermann/opal', branch: 'es6_modules_string'`
48
-
49
- - [PR#1976](https://github.com/opal/opal/pull/1976), (recommended) implementing ES6 modules and changes for 'strict' mode,
50
- based on Opal master 1.1.0 using javascript string primitives and providing nice features like `require_lazy 'my_module'`
51
-
52
- `gem 'opal', github: 'janbiedermann/opal', branch: 'es6_modules_1_1'`
53
-
54
- - if you have the webpacker gem installed somewhere, it should be a version supporting webpack 4
55
- - ruby, version 2.5 or higher recommended
56
- - bundler, latest version recommended
57
-
58
- ### Installation
59
-
60
- #### Using the installer
61
- First install the gem:
62
- ```
63
- gem install 'opal-webpack-loader'
64
- ```
65
-
66
- Continue here:
67
- - [Install for Rails like projects](https://github.com/isomorfeus/opal-webpack-loader/blob/master/docs/installation_rails.md)
68
- - [Install for Cuba, Roda, Sinatra and other projects with a flat structure](https://github.com/isomorfeus/opal-webpack-loader/blob/master/docs/installation_flat.md)
69
- - [Manual Installation](https://github.com/isomorfeus/opal-webpack-loader/blob/master/docs/installation_manual.md)
70
-
71
- ### Example applications
72
- - [Are here](https://github.com/isomorfeus/opal-webpack-loader/tree/master/example_apps/)
73
- - A minimal webpack only example from @sunrick is [here](https://github.com/sunrick/opal-hello-world-webpack).
74
-
75
- ### General Usage without Webpacker
76
-
77
- After installing owl with the installer, three scripts are provided in package.json:
78
- - `development` - runs the webpack-dev-server, use for general development, provides fast reloads, entry is application.js
79
- - `debug` - runs the webpack-dev-server, use for debugging, provides source maps, entry is application_debug.js. Additional debugging tools may be added there.
80
- - `production_build` - runs webpack to build assets for production, entry is application.js
81
-
82
- These scripts can for example be run with:
83
- `yarn run debug` or `npm run debug`
84
-
85
- The default config provides several targets and entries:
86
-
87
- - **Browser**: the webpack target is 'web' and the javascript entry file for imports is `application.js` - general use for the application with all
88
- browser features, the opal ruby entry file is `opal_loader.rb` in the opal or app/opal directory of the app.
89
- - **Server Side Rendering**: the webpack target is `node` and the javascript entry file for imports is `application_ssr.js` - general use for the
90
- application server side rendering, several Browser features are unavailable, no `window`, no `document`, some node features are available,
91
- like `Buffer`, the opal ruby entry file is `opal_loader.rb` in the opal or app/opal directory of the app.
92
- (meant to be used with isomorfeus-speednode, standard ExecJS limitations prevent certain webpack features)
93
- - **Web Worker**: the webpack target is 'webworker' and the javascript entry file for imports is `application_webworker.js` - used to initialize Web
94
- Workers in the browser, the opal ruby entry file is `opal_webworker_loader.rb` in the opal or app/opal directory of the app.
95
-
96
- Only the browser target is build by default. To builds the other target, just add the needed targets to the last line of the webpack config,
97
- for example to `development.js`:
98
- default config:
99
- ```javascript
100
- module.exports = [ browser ];
101
- ```
102
- modified config with ssr and web_worker targets enabled:
103
- ```javascript
104
- module.exports = [ browser, ssr, web_worker ];
105
- ```
106
- Same works for the `debug.js` and `production.js` webpack config files.
107
-
108
- Also a Procfile has been installed, for rails its easy to startup rails and webpack with foreman:
109
- `foreman start` (`gem install foreman` if you dont have it already). It will start rails and webpack-dev-server with the development script.
110
-
111
- For non rails installation check the Procfile and add a starter for your app.
112
-
113
- #### Opal Ruby Application Files
114
- For rails installations with the installer they all go into: `app/opal`, for flat installations in the `opal` directory.
115
- In this directory there already is a `opal_loader.rb` which is the entry point for your app.
116
-
117
- #### Stylesheets
118
- Stylesheets are hot reloaded too with the default config installed by the installer. Also they are imported into application.js by default.
119
- For rails like applications stylesheets are in `app/assets/stylesheets/application.css`, for flat applications they are in `styles/application.css`.
120
- SCSS is supported too by the default config.
121
-
122
- #### Views
123
- For rails like applications a watcher for `app/views` is installed by default. The watcher will trigger a page reload when views are changed.
124
- For flat applications nothing is configured by default, as there are to many ways to generate views, they are not even needed with
125
- frameworks like isomorfeus. Instead the section for configuring a view watcher is included in the development.js and debug.js webpack
126
- config, but it is commented out. Please see those files and adjust to your liking.
127
-
128
- #### Parallel compilation for speed
129
-
130
- Since version 0.8.0 the number of CPUs is automatically determined and a appropriate number of of compile server workers is started automatically.
131
-
132
- ### Source Maps
133
-
134
- [Source Maps](https://github.com/isomorfeus/opal-webpack-loader/blob/master/docs/source_maps.md)
135
-
136
- ### Hot Module Reloading
137
- [Hot Module Reloading](https://github.com/isomorfeus/opal-webpack-loader/blob/master/docs/hot_module_reloading.md)
138
-
139
- ### Opal Load Path
140
- The projects directory for opal ruby files must be in the opal load path. This is done in the initializer for rails apps in
141
- config/initializers/opal_webpack_loader.rb or in 'owl_init.rb' for non rails apps, for example:
142
- ```ruby
143
- Opal.append_path(File.realdirpath('app/opal'))
144
- ```
145
-
146
- ### View Helper
147
- In Rails or frameworks that support `javscript_include_tag`, add to the app/helpers/application_helper.rb
148
- ```ruby
149
- module ApplicationHelper
150
- include OpalWebpackLoader::RailsViewHelper
151
- ```
152
- in other frameworks that dont have a `javascript_include_tag`:
153
- ```ruby
154
- module MyProjectsViewThings
155
- include OpalWebpackLoader::ViewHelper
156
- ```
157
-
158
- Then you can use in your views:
159
- ```ruby
160
- owl_script_tag('application.js')
161
- ```
162
- #### Compile Server and app_loader.rb
163
- For non rails projects, determining Opal load paths, for the resolver and compile server to work properly, may not be obvious. For these cases
164
- a file `app_loader.rb` in the projects root can be created which just loads all requirements without starting anything.
165
- Usually it would just setup bundler with the appropriate options, for example:
166
- ```ruby
167
- require 'bundler/setup'
168
- if ENV['RACK_ENV'] && ENV['RACK_ENV'] == 'test'
169
- Bundler.require(:default, :test)
170
- elsif ENV['RACK_ENV'] && ENV['RACK_ENV'] == 'production'
171
- Bundler.require(:default, :production)
172
- else
173
- Bundler.require(:default, :development)
174
- end
175
- Opal.append_path(File.realdirpath('opal')) # this is a good place to add the directory with opal files to the opal load path
176
- ```
177
- When this file exists, the compile server will load it and generate Opal load paths accordingly for the resolver.
178
-
179
- #### Project configuration options for the view helper
180
- These setting are in the initializer in config/initializers/opal_webpack_loader.rb for rails like apps, or owl_init.rb for others.
181
- ```ruby
182
- OpalWebpackLoader.use_manifest = false
183
- ```
184
- If the manifest file should be used, use_manifest should be true.
185
- ```ruby
186
- OpalWebpackLoader.manifest_path = File.join(Dir.getwd, 'public', 'assets', 'manifest.json')
187
- ```
188
- Sets the path to the webpack (with the [webpack-manifest-plugin](https://www.npmjs.com/package/webpack-manifest-plugin)) generated manifest.json to look up assets.
189
- ```ruby
190
- OpalWebpackLoader.client_asset_path = 'http://localhost:3035/assets/'
191
- ```
192
- The path to prepend to the assets as configured in the webpack config 'publicPath'.
193
- In the config example below its `publicPath: 'http://localhost:3025/assets'` so
194
- client_asset_path should be set to the same.
195
-
196
- For **production** use with readily precompiled and compressed assets which contain a fingerprint in the name (webpacks [chunkhash]),
197
- and if the path in the manifest is the full path to the asset as configured in webpack,
198
- these settings would work:
199
- ```ruby
200
- OpalWebpackLoader.use_manifest = true
201
- OpalWebpackLoader.manifest_path = File.join(Dir.getwd, 'public', 'assets', 'manifest.json')
202
- OpalWebpackLoader.client_asset_path = ''
203
- ```
204
-
205
- For **development** use with webpack-dev-server, with no manifest, these settings would work:
206
- ```ruby
207
- OpalWebpackLoader.use_manifest = false
208
- OpalWebpackLoader.manifest_path = File.join(Dir.getwd, 'public', 'assets', 'manifest.json') # doesn't matter, not used
209
- OpalWebpackLoader.client_asset_path = 'http://localhost:3035/assets/'
210
- ```
211
- ### Advanced Options
212
- [Advanced Options](https://github.com/isomorfeus/opal-webpack-loader/blob/master/docs/advanced_options.md)
213
- ### Tests
214
- - clone the repo
215
- - `bundle install`
216
- - `bundle exec rspec`
1
+ <h1 align="center">
2
+ <img src="https://raw.githubusercontent.com/isomorfeus/opal-webpack-loader/master/docs/owl.png"
3
+ align="center" title="Opal logo by Elia Schito combined with Webpack Logo" width="111" height="125" />
4
+ <br/>
5
+ opal-webpack-loader<br/>
6
+ <img src="https://img.shields.io/badge/Opal-Ruby%20💛%20JavaScript%20💛%20Webpack-yellow.svg?logo=ruby&style=social&logoColor=777"/>
7
+ </h1>
8
+
9
+ Bundle assets with webpack, resolve and compile opal ruby files and import them in the bundle, without sprockets or the webpacker gem
10
+ (but can be used with both of them too).
11
+ Includes a loader and resolver plugin for webpack.
12
+
13
+ ### Community and Support
14
+ At the [Isomorfeus Framework Project](http://isomorfeus.com)
15
+
16
+ ### Tested
17
+ [TravisCI](https://travis-ci.org): [![Build Status](https://travis-ci.org/isomorfeus/opal-webpack-loader.svg?branch=master)](https://travis-ci.org/isomorfeus/opal-webpack-loader)
18
+
19
+ ### Features
20
+ - comes with a installer for rails and other frameworks
21
+ - webpack based build process
22
+ - very fast, asynchronous and parallel builds of opal code:
23
+ opal-webpack-loader-0.7.1 compiles all of opal, a bunch of gems and over 19000SLC on a
24
+ Intel® Core™ i7-7700HQ CPU @ 2.80GHz × 8, with 8 workers in around 1850ms
25
+ - support for memcached or redis as compiler cache
26
+ - fast builds on windows too, parallel when building multiple assets with parallel-webpack
27
+ - opal modules are packaged as es6 modules
28
+ - support for rails with webpacker
29
+ - other webpack features become available, like:
30
+ - source maps
31
+ - multiple targets: web (for browsers), node (for server side rendering) and webworker (for Web Workers)
32
+ - hot module reloading for opal ruby code and stylesheets and html views
33
+ - tree shaking
34
+ - code splitting
35
+ - lazy loading
36
+ - everything else webpack can do, like loading stylesheets, etc.
37
+
38
+ ### Requirements
39
+ - npm or yarn
40
+ - opal-webpack-loader consists of 2 parts, the npm package and the gem, both are required and must be the same version.
41
+ - webpack ^4.46
42
+ - webpack-dev-server ^3.11.0
43
+ - the ES6 modules branch of opal
44
+
45
+ - [PR#2266](https://github.com/opal/opal/pull/2266),
46
+ based on Opal 1.2.0 using javascript string primitives and providing nice features like `require_lazy 'my_module'`
47
+
48
+ `gem 'opal', github: 'janbiedermann/opal', branch: 'es6_modules_1_2'`
49
+
50
+ - if you have the webpacker gem installed somewhere, it should be a version supporting webpack 4
51
+ - ruby, version 2.5 or higher recommended
52
+ - bundler, latest version recommended
53
+
54
+ ### Installation
55
+
56
+ #### Using the installer
57
+ First install the gem:
58
+ ```
59
+ gem install 'opal-webpack-loader'
60
+ ```
61
+
62
+ Continue here:
63
+ - [Install for Rails like projects](https://github.com/isomorfeus/opal-webpack-loader/blob/master/docs/installation_rails.md)
64
+ - [Install for Cuba, Roda, Sinatra and other projects with a flat structure](https://github.com/isomorfeus/opal-webpack-loader/blob/master/docs/installation_flat.md)
65
+ - [Manual Installation](https://github.com/isomorfeus/opal-webpack-loader/blob/master/docs/installation_manual.md)
66
+
67
+ ### Example applications
68
+ - [Are here](https://github.com/isomorfeus/opal-webpack-loader/tree/master/example_apps/)
69
+ - A minimal webpack only example from @sunrick is [here](https://github.com/sunrick/opal-hello-world-webpack).
70
+
71
+ ### General Usage without Webpacker
72
+
73
+ After installing owl with the installer, three scripts are provided in package.json:
74
+ - `development` - runs the webpack-dev-server, use for general development, provides fast reloads, entry is application.js
75
+ - `debug` - runs the webpack-dev-server, use for debugging, provides source maps, entry is application_debug.js. Additional debugging tools may be added there.
76
+ - `production_build` - runs webpack to build assets for production, entry is application.js
77
+
78
+ These scripts can for example be run with:
79
+ `yarn run debug` or `npm run debug`
80
+
81
+ The default config provides several targets and entries:
82
+
83
+ - **Browser**: the webpack target is 'web' and the javascript entry file for imports is `application.js` - general use for the application with all
84
+ browser features, the opal ruby entry file is `opal_loader.rb` in the opal or app/opal directory of the app.
85
+ - **Server Side Rendering**: the webpack target is `node` and the javascript entry file for imports is `application_ssr.js` - general use for the
86
+ application server side rendering, several Browser features are unavailable, no `window`, no `document`, some node features are available,
87
+ like `Buffer`, the opal ruby entry file is `opal_loader.rb` in the opal or app/opal directory of the app.
88
+ (meant to be used with isomorfeus-speednode, standard ExecJS limitations prevent certain webpack features)
89
+ - **Web Worker**: the webpack target is 'webworker' and the javascript entry file for imports is `application_webworker.js` - used to initialize Web
90
+ Workers in the browser, the opal ruby entry file is `opal_webworker_loader.rb` in the opal or app/opal directory of the app.
91
+
92
+ Only the browser target is build by default. To builds the other target, just add the needed targets to the last line of the webpack config,
93
+ for example to `development.js`:
94
+ default config:
95
+ ```javascript
96
+ module.exports = [ browser ];
97
+ ```
98
+ modified config with ssr and web_worker targets enabled:
99
+ ```javascript
100
+ module.exports = [ browser, ssr, web_worker ];
101
+ ```
102
+ Same works for the `debug.js` and `production.js` webpack config files.
103
+
104
+ Also a Procfile has been installed, for rails its easy to startup rails and webpack with foreman:
105
+ `foreman start` (`gem install foreman` if you dont have it already). It will start rails and webpack-dev-server with the development script.
106
+
107
+ For non rails installation check the Procfile and add a starter for your app.
108
+
109
+ #### Opal Ruby Application Files
110
+ For rails installations with the installer they all go into: `app/opal`, for flat installations in the `opal` directory.
111
+ In this directory there already is a `opal_loader.rb` which is the entry point for your app.
112
+
113
+ #### Stylesheets
114
+ Stylesheets are hot reloaded too with the default config installed by the installer. Also they are imported into application.js by default.
115
+ For rails like applications stylesheets are in `app/assets/stylesheets/application.css`, for flat applications they are in `styles/application.css`.
116
+ SCSS is supported too by the default config.
117
+
118
+ #### Views
119
+ For rails like applications a watcher for `app/views` is installed by default. The watcher will trigger a page reload when views are changed.
120
+ For flat applications nothing is configured by default, as there are to many ways to generate views, they are not even needed with
121
+ frameworks like isomorfeus. Instead the section for configuring a view watcher is included in the development.js and debug.js webpack
122
+ config, but it is commented out. Please see those files and adjust to your liking.
123
+
124
+ #### Parallel compilation for speed
125
+
126
+ Since version 0.8.0 the number of CPUs is automatically determined and a appropriate number of of compile server workers is started automatically.
127
+
128
+ ### Source Maps
129
+
130
+ [Source Maps](https://github.com/isomorfeus/opal-webpack-loader/blob/master/docs/source_maps.md)
131
+
132
+ ### Hot Module Reloading
133
+ [Hot Module Reloading](https://github.com/isomorfeus/opal-webpack-loader/blob/master/docs/hot_module_reloading.md)
134
+
135
+ ### Opal Load Path
136
+ The projects directory for opal ruby files must be in the opal load path. This is done in the initializer for rails apps in
137
+ config/initializers/opal_webpack_loader.rb or in 'owl_init.rb' for non rails apps, for example:
138
+ ```ruby
139
+ Opal.append_path(File.realdirpath('app/opal'))
140
+ ```
141
+
142
+ ### View Helper
143
+ In Rails or frameworks that support `javscript_include_tag`, add to the app/helpers/application_helper.rb
144
+ ```ruby
145
+ module ApplicationHelper
146
+ include OpalWebpackLoader::RailsViewHelper
147
+ ```
148
+ in other frameworks that dont have a `javascript_include_tag`:
149
+ ```ruby
150
+ module MyProjectsViewThings
151
+ include OpalWebpackLoader::ViewHelper
152
+ ```
153
+
154
+ Then you can use in your views:
155
+ ```ruby
156
+ owl_script_tag('application.js')
157
+ ```
158
+ #### Compile Server and app_loader.rb
159
+ For non rails projects, determining Opal load paths, for the resolver and compile server to work properly, may not be obvious. For these cases
160
+ a file `app_loader.rb` in the projects root can be created which just loads all requirements without starting anything.
161
+ Usually it would just setup bundler with the appropriate options, for example:
162
+ ```ruby
163
+ require 'bundler/setup'
164
+ if ENV['RACK_ENV'] && ENV['RACK_ENV'] == 'test'
165
+ Bundler.require(:default, :test)
166
+ elsif ENV['RACK_ENV'] && ENV['RACK_ENV'] == 'production'
167
+ Bundler.require(:default, :production)
168
+ else
169
+ Bundler.require(:default, :development)
170
+ end
171
+ Opal.append_path(File.realdirpath('opal')) # this is a good place to add the directory with opal files to the opal load path
172
+ ```
173
+ When this file exists, the compile server will load it and generate Opal load paths accordingly for the resolver.
174
+
175
+ #### Project configuration options for the view helper
176
+ These setting are in the initializer in config/initializers/opal_webpack_loader.rb for rails like apps, or owl_init.rb for others.
177
+ ```ruby
178
+ OpalWebpackLoader.use_manifest = false
179
+ ```
180
+ If the manifest file should be used, use_manifest should be true.
181
+ ```ruby
182
+ OpalWebpackLoader.manifest_path = File.join(Dir.getwd, 'public', 'assets', 'manifest.json')
183
+ ```
184
+ Sets the path to the webpack (with the [webpack-manifest-plugin](https://www.npmjs.com/package/webpack-manifest-plugin)) generated manifest.json to look up assets.
185
+ ```ruby
186
+ OpalWebpackLoader.client_asset_path = 'http://localhost:3035/assets/'
187
+ ```
188
+ The path to prepend to the assets as configured in the webpack config 'publicPath'.
189
+ In the config example below its `publicPath: 'http://localhost:3025/assets'` so
190
+ client_asset_path should be set to the same.
191
+
192
+ For **production** use with readily precompiled and compressed assets which contain a fingerprint in the name (webpacks [chunkhash]),
193
+ and if the path in the manifest is the full path to the asset as configured in webpack,
194
+ these settings would work:
195
+ ```ruby
196
+ OpalWebpackLoader.use_manifest = true
197
+ OpalWebpackLoader.manifest_path = File.join(Dir.getwd, 'public', 'assets', 'manifest.json')
198
+ OpalWebpackLoader.client_asset_path = ''
199
+ ```
200
+
201
+ For **development** use with webpack-dev-server, with no manifest, these settings would work:
202
+ ```ruby
203
+ OpalWebpackLoader.use_manifest = false
204
+ OpalWebpackLoader.manifest_path = File.join(Dir.getwd, 'public', 'assets', 'manifest.json') # doesn't matter, not used
205
+ OpalWebpackLoader.client_asset_path = 'http://localhost:3035/assets/'
206
+ ```
207
+ ### Advanced Options
208
+ [Advanced Options](https://github.com/isomorfeus/opal-webpack-loader/blob/master/docs/advanced_options.md)
209
+ ### Tests
210
+ - clone the repo
211
+ - `bundle install`
212
+ - `bundle exec rspec`
@@ -1,415 +1,415 @@
1
- module OpalWebpackLoader
2
- module Installer
3
- TARGETS = %w[development.js production.js test.js]
4
- DEV_START_COMMAND = 'yarn run development'
5
- DEV_SM_START_COMMAND = 'yarn run sourcemaps'
6
-
7
- class CLI < Thor
8
- desc "iso", "Install owl configuration into a existing isomorfeus project, meant to be called from the isomorfeus installer only."
9
- # Showing directories and files relevant to iso owl:
10
- # project_root
11
- # +- config.ru # rack app starter
12
- # +- config # webpack and other config
13
- # +- owl.rb # owl.configuration
14
- # +- isomorfeus
15
- # +- components
16
- # +- imports # javascript entrypoints, import other components etc.
17
- # +- application.js
18
- # +- application_common.js
19
- # +- application_ssr.js
20
- # +- isomorfeus_loader.rb
21
- # +- models
22
- # +- operations
23
- # +- policies
24
- # +- styles
25
- # +- css
26
- # +- log
27
- # +- node_modules
28
- # +- package.json
29
- # +- Procfile
30
- # +- public
31
- # +- assets # compiled assets and other things
32
- # +- spec
33
- # +- tmp
34
- def iso
35
- @application_css = '../styles/application.css'
36
- @asset_output_directory = File.join('public', 'assets')
37
- @js_entrypoints_directory = File.join('isomorfeus', 'imports')
38
- @conf_rel_prefix = '..'
39
- @js_rel_prefix = '..'
40
- @opal_directory = 'isomorfeus'
41
- @styles_directory = File.join(@opal_directory, 'styles')
42
- @webpack_config_directory = 'webpack'
43
- @dev_default_targets = 'browser'
44
- @pro_default_targets = 'browser, ssr'
45
- @hmr_hook = 'Opal.Isomorfeus.$force_render()'
46
- create_directory(@webpack_config_directory)
47
- create_directory(@asset_output_directory)
48
- FileUtils.touch(File.join(@asset_output_directory, '.keep'))
49
- install_webpack_config
50
- create_file_from_template('initializer.rb.erb', File.join('owl_init.rb'), { opal_load_path: '' })
51
- # add_gem
52
- end
53
-
54
- desc "flat", "Install owl configuration into a existing project with a flat structure, execute from the projects root directory."
55
- # <<~TEXT
56
- # Showing directories and files relevant to owl:
57
- # project_root
58
- # +- owl_init.rb # initializer for owl
59
- # +- javascripts # javascript entries directory
60
- # +- node_modules # directory for node modules
61
- # +- opal # directory for opal application files, can be changed with -o
62
- # +- package.json # package config for npm/yarn and their scripts
63
- # +- public
64
- # +- assets # directory for compiled output files
65
- # +- styles # directory for stylesheets
66
- # +- webpack # directory for webpack configuration files
67
- # +- Procfile # config file for foreman
68
- #
69
- # TEXT
70
- option :opal_name, required: false, type: :string, default: 'opal', aliases: '-o', desc: <<~TEXT
71
- Set directory name for Opal source files.
72
- Example: owl-installer rails -o isomorfeus # will use project_root/app/isomorfeus for opal files
73
- TEXT
74
-
75
- def flat
76
- @application_css = '../styles/application.css'
77
- @asset_output_directory = File.join('public', 'assets')
78
- @js_entrypoints_directory = File.join('javascripts')
79
- @conf_rel_prefix = '..'
80
- @js_rel_prefix = '..'
81
- @opal_directory = options[:opal_name]
82
- @styles_directory = 'styles'
83
- @webpack_config_directory = 'webpack'
84
- @dev_default_targets = 'browser'
85
- @pro_default_targets = 'browser'
86
- @hmr_hook = ''
87
- create_common_directories
88
- install_common_things
89
- create_file_from_template('application.css.erb', File.join('styles', 'application.css'), {})
90
- create_file_from_template('initializer.rb.erb', 'owl_init.rb', { opal_load_path: '' })
91
- create_file_from_template('app_loader.rb.erb', 'app_loader.rb', { opal_directory: @opal_directory })
92
- add_gem
93
- print_message
94
- end
95
-
96
- desc "rails", "Install owl configuration into a existing rails project without webpacker, execute from the projects root directory."
97
- # <<~TEXT
98
- # Showing directories and files relevant to owl:
99
- # project_root
100
- # +- app
101
- # +- assets
102
- # +- javascripts # javascript entries directory
103
- # +- styles # directory for stylesheets
104
- # +- opal # directory for opal application files, can be changed with -o
105
- # +- config
106
- # +- webpack # directory for webpack configuration files
107
- # +- initializers
108
- # +- owl.rb # initializer for owl
109
- # +- node_modules # directory for node modules
110
- # +- package.json # package config for npm/yarn and their scripts
111
- # +- public
112
- # +- assets # directory for compiled output files
113
- # +- Procfile # config file for foreman
114
- #
115
- # TEXT
116
- option :opal_name, required: false, type: :string, default: 'opal', aliases: '-o', desc: <<~TEXT
117
- Set directory name for Opal source files.
118
- Example: owl-installer rails -o isomorfeus # will use project_root/app/isomorfeus for opal files
119
- TEXT
120
-
121
- def rails
122
- @application_css = '../stylesheets/application.css'
123
- @asset_output_directory = File.join('public', 'assets')
124
- @js_entrypoints_directory = File.join('app', 'assets', 'javascripts')
125
- @conf_rel_prefix = File.join('..', '..')
126
- @js_rel_prefix = File.join('..', '..', '..')
127
- @opal_directory = File.join('app', options[:opal_name])
128
- @styles_directory = File.join('app', 'assets', 'stylesheets')
129
- @webpack_config_directory = File.join('config', 'webpack')
130
- @dev_default_targets = 'browser'
131
- @pro_default_targets = 'browser'
132
- @hmr_hook = ''
133
- create_directory('app')
134
- create_common_directories
135
- install_common_things
136
- create_file_from_template('initializer.rb.erb', File.join('config', 'initializers', 'opal_webpack_loader.rb'),
137
- { opal_load_path: "Opal.append_path(File.realdirpath('#{@opal_directory}'))" })
138
- add_gem
139
- print_message
140
- end
141
-
142
- desc "webpacker", "Install owl configuration into a existing rails project with webpacker, execute from the projects root directory."
143
- # <<~TEXT
144
- # Showing directories and files relevant to owl:
145
- # project_root
146
- # +- app
147
- # +- assets
148
- # +- javascripts # javascript entries directory
149
- # +- styles # directory for stylesheets
150
- # +- opal # directory for opal application files, can be changed with -o
151
- # +- config
152
- # +- webpack # directory for webpack configuration files
153
- # +- initializers
154
- # +- owl.rb # initializer for owl
155
- # +- node_modules # directory for node modules
156
- # +- package.json # package config for npm/yarn and their scripts
157
- # +- public
158
- # +- assets # directory for compiled output files
159
- # +- Procfile # config file for foreman
160
- #
161
- # TEXT
162
- option :opal_name, required: false, type: :string, default: 'opal', aliases: '-o', desc: <<~TEXT
163
- Set directory name for Opal source files.
164
- Example: owl-installer rails -o isomorfeus # will use project_root/app/isomorfeus for opal files
165
- TEXT
166
-
167
- def webpacker
168
- @application_css = '../stylesheets/application.css'
169
- @asset_output_directory = File.join('public', 'assets')
170
- @js_entrypoints_directory = File.join('app', 'assets', 'javascripts')
171
- @conf_rel_prefix = File.join('..', '..')
172
- @js_rel_prefix = File.join('..', '..', '..')
173
- @opal_directory = File.join('app', options[:opal_name])
174
- @styles_directory = File.join('app', 'assets', 'stylesheets')
175
- @webpack_config_directory = File.join('config', 'webpack')
176
- @dev_default_targets = 'browser'
177
- @pro_default_targets = 'browser'
178
- @hmr_hook = ''
179
- create_directory('app')
180
- create_common_directories
181
- install_webpacker_config
182
- install_webpacker_package_json
183
- install_webpacker_js_entry
184
- install_opal_entries
185
- create_file_from_template('initializer.rb.erb', File.join('config', 'initializers', 'opal_webpack_loader.rb'),
186
- { opal_load_path: "Opal.append_path(File.realdirpath('#{@opal_directory}'))" })
187
- add_gem
188
- print_message
189
- end
190
-
191
- private
192
-
193
- def create_directory(directory)
194
- unless Dir.exist?(directory)
195
- puts "Creating directory #{directory}."
196
- FileUtils.mkdir_p(directory)
197
- end
198
- end
199
-
200
- def create_common_directories
201
- create_directory(@webpack_config_directory)
202
- create_directory(@js_entrypoints_directory)
203
- create_directory(@opal_directory)
204
- create_directory(@asset_output_directory)
205
- FileUtils.touch(File.join(@asset_output_directory, '.gitkeep'))
206
- create_directory(@styles_directory)
207
- end
208
-
209
- def install_common_things
210
- install_webpack_config
211
- install_package_json
212
- install_js_entries
213
- install_opal_entries
214
- install_procfile
215
- end
216
-
217
- def install_js_entries
218
- erb_hash = { opal_dir: File.join(@js_rel_prefix, @opal_directory), opal_name: options[:opal_name], application_css: @application_css }
219
- create_file_from_template('application.js.erb', File.join(@js_entrypoints_directory, 'application.js'), erb_hash)
220
- create_file_from_template('application_common.js.erb', File.join(@js_entrypoints_directory, 'application_common.js'),erb_hash)
221
- create_file_from_template('application_ssr.js.erb', File.join(@js_entrypoints_directory, 'application_ssr.js'), erb_hash)
222
- create_file_from_template('application_web_worker.js.erb', File.join(@js_entrypoints_directory, 'application_web_worker.js'), erb_hash)
223
- end
224
-
225
- def install_opal_entries
226
- create_file_from_template('opal_loader.rb.erb', File.join(@opal_directory, "#{options[:opal_name]}_loader.rb"), {})
227
- create_file_from_template('opal_web_worker_loader.rb.erb', File.join(@opal_directory, "#{options[:opal_name]}_web_worker_loader.rb"), {})
228
- end
229
-
230
- def install_package_json
231
- if File.exist?('package.json')
232
- gem_package_json_template = File.read(File.join(templates_path, 'package.json.erb'))
233
- gem_package_json = Oj.load(gem_package_json_template, mode: :strict)
234
- package_json_file = File.read('package.json')
235
- package_json = Oj.load(package_json_file, mode: :strict)
236
- package_json["scripts"] = {} unless package_json.has_key?("scripts")
237
- package_json["scripts"]["debug"] = debug_script
238
- package_json["scripts"]["development"] = development_script
239
- package_json["scripts"]["production_build"] = production_script
240
- package_json["devDependencies"] = {} unless package_json.has_key?("devDependencies")
241
- package_json["devDependencies"].merge!(gem_package_json["devDependencies"])
242
- package_json["dependencies"]["opal-webpack-loader"] = "^#{OpalWebpackLoader::VERSION}"
243
- File.write('package.json', Oj.dump(package_json, mode: :strict, indent: 2))
244
- puts "Updated package.json, updated scripts and owl dependencies"
245
- else
246
- erb_hash = {
247
- debug_script: debug_script,
248
- development_script: development_script,
249
- production_script: production_script,
250
- owl_version: OpalWebpackLoader::VERSION
251
- }
252
- create_file_from_template('package.json.erb', 'package.json', erb_hash)
253
- end
254
- end
255
-
256
- def install_procfile
257
- if File.exist?('Procfile')
258
- procfile = File.read('Procfile')
259
- has_webpack = false
260
- lines = procfile.lines
261
- lines.each do |line|
262
- has_webpack = true if line.start_with?('webpack')
263
- end
264
- unless has_webpack
265
- lines << 'webpack: yarn run development'
266
- File.write('Procfile', lines.join("\n"))
267
- end
268
- else
269
- erb_hash = { web_starter: '' }
270
- if @js_entrypoints_directory.start_with?('app')
271
- erb_hash[:web_starter] = 'web: bundle exec rails s'
272
- end
273
- create_file_from_template('Procfile.erb', 'Procfile',erb_hash)
274
- end
275
- end
276
-
277
- def debug_script
278
- "webpack-dev-server --config #{File.join(@webpack_config_directory, 'debug.js')}"
279
- end
280
-
281
- def development_script
282
- "webpack-dev-server --config #{File.join(@webpack_config_directory, 'development.js')}"
283
- end
284
-
285
- def production_script
286
- "parallel-webpack --config=#{File.join(@webpack_config_directory, 'production.js')}"
287
- end
288
-
289
- def install_webpack_config
290
- erb_hash = {
291
- asset_output_directory: File.join(@conf_rel_prefix, @asset_output_directory),
292
- default_targets: @dev_default_targets,
293
- js_entry: File.join(@conf_rel_prefix, @js_entrypoints_directory, 'application.js'),
294
- js_common_entry: File.join(@conf_rel_prefix, @js_entrypoints_directory, 'application_common.js'),
295
- js_ssr_entry: File.join(@conf_rel_prefix, @js_entrypoints_directory, 'application_ssr.js'),
296
- js_web_worker_entry: File.join(@conf_rel_prefix, @js_entrypoints_directory, 'application_web_worker.js'),
297
- opal_directory: File.join(@conf_rel_prefix, @opal_directory),
298
- stylesheets_directory: File.join(@conf_rel_prefix, @styles_directory),
299
- hmr_hook: @hmr_hook
300
- }
301
- if @js_entrypoints_directory.start_with?('app')
302
- erb_hash[:dev_server_before] = <<~JAVASCRIPT
303
- // enable page reload for updates within the app/views directory
304
- before: function(app, server) {
305
- chokidar.watch(path.resolve(__dirname, path.join('..', '..', 'app', 'views'))).on('all', function () {
306
- server.sockWrite(server.sockets, 'content-changed');
307
- })
308
- },
309
- JAVASCRIPT
310
- else
311
- erb_hash[:dev_server_before] = <<~JAVASCRIPT
312
- // uncomment to enable page reload for updates within another directory, which may contain just html files,
313
- // for example the 'views' directory:
314
- // before: function(app, server) {
315
- // chokidar.watch(path.resolve(__dirname, path.join('..', 'views')).on('all', function () {
316
- // server.sockWrite(server.sockets, 'content-changed');
317
- // })
318
- // },
319
- JAVASCRIPT
320
- end
321
- create_file_from_template('debug.js.erb', File.join(@webpack_config_directory, 'debug.js'), erb_hash)
322
- create_file_from_template('development.js.erb', File.join(@webpack_config_directory, 'development.js'), erb_hash)
323
- erb_hash[:default_targets] = @pro_default_targets
324
- create_file_from_template('production.js.erb', File.join(@webpack_config_directory, 'production.js'), erb_hash)
325
- end
326
-
327
- def install_webpacker_config
328
- environment_js = File.read(File.join('config', 'webpack', 'environment.js'), mode: 'r')
329
- new_environment_js = ''
330
- environment_js.lines.each do |line|
331
- new_environment_js << line
332
- if line.start_with?('const { environment }')
333
- new_environment_js << "\n"
334
- new_environment_js << File.read(File.join(templates_path, 'webpacker.js'), mode: 'r')
335
- new_environment_js << "\n"
336
- end
337
- end
338
- File.write(File.join('config', 'webpack', 'environment.js'), new_environment_js)
339
- end
340
-
341
- def install_webpacker_js_entry
342
- application_js = File.read(File.join('app', 'javascript', 'packs', 'application.js'), mode: 'r')
343
- application_js << <<~JAVASCRIPT
344
-
345
- // import and load opal ruby files
346
- import init_app from '#{options[:opal_name]}_loader.rb';
347
- init_app();
348
- Opal.load('#{options[:opal_name]}_loader');
349
-
350
- JAVASCRIPT
351
- File.write(File.join('app', 'javascript', 'packs', 'application.js'), application_js)
352
- end
353
-
354
- def install_webpacker_package_json
355
- package_json_file = File.read('package.json')
356
- package_json = Oj.load(package_json_file, mode: :strict)
357
- package_json["dependencies"]["opal-webpack-loader"] = "^#{OpalWebpackLoader::VERSION}"
358
- File.write('package.json', Oj.dump(package_json, mode: :strict, indent: 2))
359
- puts "Updated package.json for opal-webpack-loader"
360
- end
361
-
362
- def templates_path
363
- File.realpath(File.join(File.dirname(File.realpath(__FILE__)), 'templates'))
364
- end
365
-
366
- def create_file_from_template(template_path, target_file_path, data_hash)
367
- template = ERB.new(File.read(File.join(templates_path, template_path), mode: 'r'))
368
- result = template.result_with_hash(data_hash)
369
- if File.exist?(target_file_path)
370
- ext = '_owl_new'
371
- puts "#{target_file_path} exists, not overwriting, creating #{target_file_path + ext} instead."
372
- else
373
- ext = ''
374
- puts "Creating #{target_file_path}."
375
- end
376
-
377
- File.write(target_file_path + ext, result, mode: 'w')
378
- end
379
-
380
- def add_gem
381
- # TODO specifying a version results in bundler printing a error and not adding the gem
382
- # `bundle add opal-webpack-loader -v "#{OpalWebpackLoader::VERSION}" --skip-install`ß´
383
- end
384
-
385
- def print_message
386
- puts <<~TEXT
387
-
388
- Add the following lines to your Gemfile:
389
-
390
- gem 'opal', github: 'janbiedermann/opal', branch: 'es6_modules_1_1'
391
- gem 'opal-webpack-loader', '~> #{OpalWebpackLoader::VERSION}'
392
-
393
- owl currently works only with above opal branch. If you have a existing "gem 'opal'", please replace it with above line.
394
-
395
- Also check above output for files ending in '_owl_new' and merge their contents with the existing files.
396
-
397
- After that run according to your preference either:
398
-
399
- yarn install
400
-
401
- or:
402
-
403
- npm install
404
-
405
- and then:
406
-
407
- bundle install
408
-
409
- For further instructions see http://github.com/isomorfeus/opal-webpack-loader
410
-
411
- TEXT
412
- end
413
- end
414
- end
415
- end
1
+ module OpalWebpackLoader
2
+ module Installer
3
+ TARGETS = %w[development.js production.js test.js]
4
+ DEV_START_COMMAND = 'yarn run development'
5
+ DEV_SM_START_COMMAND = 'yarn run sourcemaps'
6
+
7
+ class CLI < Thor
8
+ desc "iso", "Install owl configuration into a existing isomorfeus project, meant to be called from the isomorfeus installer only."
9
+ # Showing directories and files relevant to iso owl:
10
+ # project_root
11
+ # +- config.ru # rack app starter
12
+ # +- config # webpack and other config
13
+ # +- owl.rb # owl.configuration
14
+ # +- isomorfeus
15
+ # +- components
16
+ # +- imports # javascript entrypoints, import other components etc.
17
+ # +- application.js
18
+ # +- application_common.js
19
+ # +- application_ssr.js
20
+ # +- isomorfeus_loader.rb
21
+ # +- models
22
+ # +- operations
23
+ # +- policies
24
+ # +- styles
25
+ # +- css
26
+ # +- log
27
+ # +- node_modules
28
+ # +- package.json
29
+ # +- Procfile
30
+ # +- public
31
+ # +- assets # compiled assets and other things
32
+ # +- spec
33
+ # +- tmp
34
+ def iso
35
+ @application_css = '../styles/application.css'
36
+ @asset_output_directory = File.join('public', 'assets')
37
+ @js_entrypoints_directory = File.join('isomorfeus', 'imports')
38
+ @conf_rel_prefix = '..'
39
+ @js_rel_prefix = '..'
40
+ @opal_directory = 'isomorfeus'
41
+ @styles_directory = File.join(@opal_directory, 'styles')
42
+ @webpack_config_directory = 'webpack'
43
+ @dev_default_targets = 'browser'
44
+ @pro_default_targets = 'browser, ssr'
45
+ @hmr_hook = 'Opal.Isomorfeus.$force_render()'
46
+ create_directory(@webpack_config_directory)
47
+ create_directory(@asset_output_directory)
48
+ FileUtils.touch(File.join(@asset_output_directory, '.keep'))
49
+ install_webpack_config
50
+ create_file_from_template('initializer.rb.erb', File.join('owl_init.rb'), { opal_load_path: '' })
51
+ # add_gem
52
+ end
53
+
54
+ desc "flat", "Install owl configuration into a existing project with a flat structure, execute from the projects root directory."
55
+ # <<~TEXT
56
+ # Showing directories and files relevant to owl:
57
+ # project_root
58
+ # +- owl_init.rb # initializer for owl
59
+ # +- javascripts # javascript entries directory
60
+ # +- node_modules # directory for node modules
61
+ # +- opal # directory for opal application files, can be changed with -o
62
+ # +- package.json # package config for npm/yarn and their scripts
63
+ # +- public
64
+ # +- assets # directory for compiled output files
65
+ # +- styles # directory for stylesheets
66
+ # +- webpack # directory for webpack configuration files
67
+ # +- Procfile # config file for foreman
68
+ #
69
+ # TEXT
70
+ option :opal_name, required: false, type: :string, default: 'opal', aliases: '-o', desc: <<~TEXT
71
+ Set directory name for Opal source files.
72
+ Example: owl-installer rails -o isomorfeus # will use project_root/app/isomorfeus for opal files
73
+ TEXT
74
+
75
+ def flat
76
+ @application_css = '../styles/application.css'
77
+ @asset_output_directory = File.join('public', 'assets')
78
+ @js_entrypoints_directory = File.join('javascripts')
79
+ @conf_rel_prefix = '..'
80
+ @js_rel_prefix = '..'
81
+ @opal_directory = options[:opal_name]
82
+ @styles_directory = 'styles'
83
+ @webpack_config_directory = 'webpack'
84
+ @dev_default_targets = 'browser'
85
+ @pro_default_targets = 'browser'
86
+ @hmr_hook = ''
87
+ create_common_directories
88
+ install_common_things
89
+ create_file_from_template('application.css.erb', File.join('styles', 'application.css'), {})
90
+ create_file_from_template('initializer.rb.erb', 'owl_init.rb', { opal_load_path: '' })
91
+ create_file_from_template('app_loader.rb.erb', 'app_loader.rb', { opal_directory: @opal_directory })
92
+ add_gem
93
+ print_message
94
+ end
95
+
96
+ desc "rails", "Install owl configuration into a existing rails project without webpacker, execute from the projects root directory."
97
+ # <<~TEXT
98
+ # Showing directories and files relevant to owl:
99
+ # project_root
100
+ # +- app
101
+ # +- assets
102
+ # +- javascripts # javascript entries directory
103
+ # +- styles # directory for stylesheets
104
+ # +- opal # directory for opal application files, can be changed with -o
105
+ # +- config
106
+ # +- webpack # directory for webpack configuration files
107
+ # +- initializers
108
+ # +- owl.rb # initializer for owl
109
+ # +- node_modules # directory for node modules
110
+ # +- package.json # package config for npm/yarn and their scripts
111
+ # +- public
112
+ # +- assets # directory for compiled output files
113
+ # +- Procfile # config file for foreman
114
+ #
115
+ # TEXT
116
+ option :opal_name, required: false, type: :string, default: 'opal', aliases: '-o', desc: <<~TEXT
117
+ Set directory name for Opal source files.
118
+ Example: owl-installer rails -o isomorfeus # will use project_root/app/isomorfeus for opal files
119
+ TEXT
120
+
121
+ def rails
122
+ @application_css = '../stylesheets/application.css'
123
+ @asset_output_directory = File.join('public', 'assets')
124
+ @js_entrypoints_directory = File.join('app', 'assets', 'javascripts')
125
+ @conf_rel_prefix = File.join('..', '..')
126
+ @js_rel_prefix = File.join('..', '..', '..')
127
+ @opal_directory = File.join('app', options[:opal_name])
128
+ @styles_directory = File.join('app', 'assets', 'stylesheets')
129
+ @webpack_config_directory = File.join('config', 'webpack')
130
+ @dev_default_targets = 'browser'
131
+ @pro_default_targets = 'browser'
132
+ @hmr_hook = ''
133
+ create_directory('app')
134
+ create_common_directories
135
+ install_common_things
136
+ create_file_from_template('initializer.rb.erb', File.join('config', 'initializers', 'opal_webpack_loader.rb'),
137
+ { opal_load_path: "Opal.append_path(File.realdirpath('#{@opal_directory}'))" })
138
+ add_gem
139
+ print_message
140
+ end
141
+
142
+ desc "webpacker", "Install owl configuration into a existing rails project with webpacker, execute from the projects root directory."
143
+ # <<~TEXT
144
+ # Showing directories and files relevant to owl:
145
+ # project_root
146
+ # +- app
147
+ # +- assets
148
+ # +- javascripts # javascript entries directory
149
+ # +- styles # directory for stylesheets
150
+ # +- opal # directory for opal application files, can be changed with -o
151
+ # +- config
152
+ # +- webpack # directory for webpack configuration files
153
+ # +- initializers
154
+ # +- owl.rb # initializer for owl
155
+ # +- node_modules # directory for node modules
156
+ # +- package.json # package config for npm/yarn and their scripts
157
+ # +- public
158
+ # +- assets # directory for compiled output files
159
+ # +- Procfile # config file for foreman
160
+ #
161
+ # TEXT
162
+ option :opal_name, required: false, type: :string, default: 'opal', aliases: '-o', desc: <<~TEXT
163
+ Set directory name for Opal source files.
164
+ Example: owl-installer rails -o isomorfeus # will use project_root/app/isomorfeus for opal files
165
+ TEXT
166
+
167
+ def webpacker
168
+ @application_css = '../stylesheets/application.css'
169
+ @asset_output_directory = File.join('public', 'assets')
170
+ @js_entrypoints_directory = File.join('app', 'assets', 'javascripts')
171
+ @conf_rel_prefix = File.join('..', '..')
172
+ @js_rel_prefix = File.join('..', '..', '..')
173
+ @opal_directory = File.join('app', options[:opal_name])
174
+ @styles_directory = File.join('app', 'assets', 'stylesheets')
175
+ @webpack_config_directory = File.join('config', 'webpack')
176
+ @dev_default_targets = 'browser'
177
+ @pro_default_targets = 'browser'
178
+ @hmr_hook = ''
179
+ create_directory('app')
180
+ create_common_directories
181
+ install_webpacker_config
182
+ install_webpacker_package_json
183
+ install_webpacker_js_entry
184
+ install_opal_entries
185
+ create_file_from_template('initializer.rb.erb', File.join('config', 'initializers', 'opal_webpack_loader.rb'),
186
+ { opal_load_path: "Opal.append_path(File.realdirpath('#{@opal_directory}'))" })
187
+ add_gem
188
+ print_message
189
+ end
190
+
191
+ private
192
+
193
+ def create_directory(directory)
194
+ unless Dir.exist?(directory)
195
+ puts "Creating directory #{directory}."
196
+ FileUtils.mkdir_p(directory)
197
+ end
198
+ end
199
+
200
+ def create_common_directories
201
+ create_directory(@webpack_config_directory)
202
+ create_directory(@js_entrypoints_directory)
203
+ create_directory(@opal_directory)
204
+ create_directory(@asset_output_directory)
205
+ FileUtils.touch(File.join(@asset_output_directory, '.gitkeep'))
206
+ create_directory(@styles_directory)
207
+ end
208
+
209
+ def install_common_things
210
+ install_webpack_config
211
+ install_package_json
212
+ install_js_entries
213
+ install_opal_entries
214
+ install_procfile
215
+ end
216
+
217
+ def install_js_entries
218
+ erb_hash = { opal_dir: File.join(@js_rel_prefix, @opal_directory), opal_name: options[:opal_name], application_css: @application_css }
219
+ create_file_from_template('application.js.erb', File.join(@js_entrypoints_directory, 'application.js'), erb_hash)
220
+ create_file_from_template('application_common.js.erb', File.join(@js_entrypoints_directory, 'application_common.js'),erb_hash)
221
+ create_file_from_template('application_ssr.js.erb', File.join(@js_entrypoints_directory, 'application_ssr.js'), erb_hash)
222
+ create_file_from_template('application_web_worker.js.erb', File.join(@js_entrypoints_directory, 'application_web_worker.js'), erb_hash)
223
+ end
224
+
225
+ def install_opal_entries
226
+ create_file_from_template('opal_loader.rb.erb', File.join(@opal_directory, "#{options[:opal_name]}_loader.rb"), {})
227
+ create_file_from_template('opal_web_worker_loader.rb.erb', File.join(@opal_directory, "#{options[:opal_name]}_web_worker_loader.rb"), {})
228
+ end
229
+
230
+ def install_package_json
231
+ if File.exist?('package.json')
232
+ gem_package_json_template = File.read(File.join(templates_path, 'package.json.erb'))
233
+ gem_package_json = Oj.load(gem_package_json_template, mode: :strict)
234
+ package_json_file = File.read('package.json')
235
+ package_json = Oj.load(package_json_file, mode: :strict)
236
+ package_json["scripts"] = {} unless package_json.has_key?("scripts")
237
+ package_json["scripts"]["debug"] = debug_script
238
+ package_json["scripts"]["development"] = development_script
239
+ package_json["scripts"]["production_build"] = production_script
240
+ package_json["devDependencies"] = {} unless package_json.has_key?("devDependencies")
241
+ package_json["devDependencies"].merge!(gem_package_json["devDependencies"])
242
+ package_json["dependencies"]["opal-webpack-loader"] = "^#{OpalWebpackLoader::VERSION}"
243
+ File.write('package.json', Oj.dump(package_json, mode: :strict, indent: 2))
244
+ puts "Updated package.json, updated scripts and owl dependencies"
245
+ else
246
+ erb_hash = {
247
+ debug_script: debug_script,
248
+ development_script: development_script,
249
+ production_script: production_script,
250
+ owl_version: OpalWebpackLoader::VERSION
251
+ }
252
+ create_file_from_template('package.json.erb', 'package.json', erb_hash)
253
+ end
254
+ end
255
+
256
+ def install_procfile
257
+ if File.exist?('Procfile')
258
+ procfile = File.read('Procfile')
259
+ has_webpack = false
260
+ lines = procfile.lines
261
+ lines.each do |line|
262
+ has_webpack = true if line.start_with?('webpack')
263
+ end
264
+ unless has_webpack
265
+ lines << 'webpack: yarn run development'
266
+ File.write('Procfile', lines.join("\n"))
267
+ end
268
+ else
269
+ erb_hash = { web_starter: '' }
270
+ if @js_entrypoints_directory.start_with?('app')
271
+ erb_hash[:web_starter] = 'web: bundle exec rails s'
272
+ end
273
+ create_file_from_template('Procfile.erb', 'Procfile',erb_hash)
274
+ end
275
+ end
276
+
277
+ def debug_script
278
+ "webpack-dev-server --config #{File.join(@webpack_config_directory, 'debug.js')}"
279
+ end
280
+
281
+ def development_script
282
+ "webpack-dev-server --config #{File.join(@webpack_config_directory, 'development.js')}"
283
+ end
284
+
285
+ def production_script
286
+ "parallel-webpack --config=#{File.join(@webpack_config_directory, 'production.js')}"
287
+ end
288
+
289
+ def install_webpack_config
290
+ erb_hash = {
291
+ asset_output_directory: File.join(@conf_rel_prefix, @asset_output_directory),
292
+ default_targets: @dev_default_targets,
293
+ js_entry: File.join(@conf_rel_prefix, @js_entrypoints_directory, 'application.js'),
294
+ js_common_entry: File.join(@conf_rel_prefix, @js_entrypoints_directory, 'application_common.js'),
295
+ js_ssr_entry: File.join(@conf_rel_prefix, @js_entrypoints_directory, 'application_ssr.js'),
296
+ js_web_worker_entry: File.join(@conf_rel_prefix, @js_entrypoints_directory, 'application_web_worker.js'),
297
+ opal_directory: File.join(@conf_rel_prefix, @opal_directory),
298
+ stylesheets_directory: File.join(@conf_rel_prefix, @styles_directory),
299
+ hmr_hook: @hmr_hook
300
+ }
301
+ if @js_entrypoints_directory.start_with?('app')
302
+ erb_hash[:dev_server_before] = <<~JAVASCRIPT
303
+ // enable page reload for updates within the app/views directory
304
+ before: function(app, server) {
305
+ chokidar.watch(path.resolve(__dirname, path.join('..', '..', 'app', 'views'))).on('all', function () {
306
+ server.sockWrite(server.sockets, 'content-changed');
307
+ })
308
+ },
309
+ JAVASCRIPT
310
+ else
311
+ erb_hash[:dev_server_before] = <<~JAVASCRIPT
312
+ // uncomment to enable page reload for updates within another directory, which may contain just html files,
313
+ // for example the 'views' directory:
314
+ // before: function(app, server) {
315
+ // chokidar.watch(path.resolve(__dirname, path.join('..', 'views')).on('all', function () {
316
+ // server.sockWrite(server.sockets, 'content-changed');
317
+ // })
318
+ // },
319
+ JAVASCRIPT
320
+ end
321
+ create_file_from_template('debug.js.erb', File.join(@webpack_config_directory, 'debug.js'), erb_hash)
322
+ create_file_from_template('development.js.erb', File.join(@webpack_config_directory, 'development.js'), erb_hash)
323
+ erb_hash[:default_targets] = @pro_default_targets
324
+ create_file_from_template('production.js.erb', File.join(@webpack_config_directory, 'production.js'), erb_hash)
325
+ end
326
+
327
+ def install_webpacker_config
328
+ environment_js = File.read(File.join('config', 'webpack', 'environment.js'), mode: 'r')
329
+ new_environment_js = ''
330
+ environment_js.lines.each do |line|
331
+ new_environment_js << line
332
+ if line.start_with?('const { environment }')
333
+ new_environment_js << "\n"
334
+ new_environment_js << File.read(File.join(templates_path, 'webpacker.js'), mode: 'r')
335
+ new_environment_js << "\n"
336
+ end
337
+ end
338
+ File.write(File.join('config', 'webpack', 'environment.js'), new_environment_js)
339
+ end
340
+
341
+ def install_webpacker_js_entry
342
+ application_js = File.read(File.join('app', 'javascript', 'packs', 'application.js'), mode: 'r')
343
+ application_js << <<~JAVASCRIPT
344
+
345
+ // import and load opal ruby files
346
+ import init_app from '#{options[:opal_name]}_loader.rb';
347
+ init_app();
348
+ Opal.load('#{options[:opal_name]}_loader');
349
+
350
+ JAVASCRIPT
351
+ File.write(File.join('app', 'javascript', 'packs', 'application.js'), application_js)
352
+ end
353
+
354
+ def install_webpacker_package_json
355
+ package_json_file = File.read('package.json')
356
+ package_json = Oj.load(package_json_file, mode: :strict)
357
+ package_json["dependencies"]["opal-webpack-loader"] = "^#{OpalWebpackLoader::VERSION}"
358
+ File.write('package.json', Oj.dump(package_json, mode: :strict, indent: 2))
359
+ puts "Updated package.json for opal-webpack-loader"
360
+ end
361
+
362
+ def templates_path
363
+ File.realpath(File.join(File.dirname(File.realpath(__FILE__)), 'templates'))
364
+ end
365
+
366
+ def create_file_from_template(template_path, target_file_path, data_hash)
367
+ template = ERB.new(File.read(File.join(templates_path, template_path), mode: 'r'))
368
+ result = template.result_with_hash(data_hash)
369
+ if File.exist?(target_file_path)
370
+ ext = '_owl_new'
371
+ puts "#{target_file_path} exists, not overwriting, creating #{target_file_path + ext} instead."
372
+ else
373
+ ext = ''
374
+ puts "Creating #{target_file_path}."
375
+ end
376
+
377
+ File.write(target_file_path + ext, result, mode: 'w')
378
+ end
379
+
380
+ def add_gem
381
+ # TODO specifying a version results in bundler printing a error and not adding the gem
382
+ # `bundle add opal-webpack-loader -v "#{OpalWebpackLoader::VERSION}" --skip-install`ß´
383
+ end
384
+
385
+ def print_message
386
+ puts <<~TEXT
387
+
388
+ Add the following lines to your Gemfile:
389
+
390
+ gem 'opal', github: 'janbiedermann/opal', branch: 'es6_modules_1_2'
391
+ gem 'opal-webpack-loader', '~> #{OpalWebpackLoader::VERSION}'
392
+
393
+ owl currently works only with above opal branch. If you have a existing "gem 'opal'", please replace it with above line.
394
+
395
+ Also check above output for files ending in '_owl_new' and merge their contents with the existing files.
396
+
397
+ After that run according to your preference either:
398
+
399
+ yarn install
400
+
401
+ or:
402
+
403
+ npm install
404
+
405
+ and then:
406
+
407
+ bundle install
408
+
409
+ For further instructions see http://github.com/isomorfeus/opal-webpack-loader
410
+
411
+ TEXT
412
+ end
413
+ end
414
+ end
415
+ end