opal-webpack-loader 0.11.4 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
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