proscenium 0.9.1-x86_64-darwin → 0.11.0.pre.1-x86_64-darwin
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +423 -63
- data/lib/proscenium/builder.rb +126 -0
- data/lib/proscenium/css_module/path.rb +31 -0
- data/lib/proscenium/css_module/transformer.rb +76 -0
- data/lib/proscenium/css_module.rb +6 -28
- data/lib/proscenium/ensure_loaded.rb +27 -0
- data/lib/proscenium/ext/proscenium +0 -0
- data/lib/proscenium/ext/proscenium.h +19 -12
- data/lib/proscenium/helper.rb +62 -0
- data/lib/proscenium/importer.rb +110 -0
- data/lib/proscenium/libs/react-manager/index.jsx +88 -0
- data/lib/proscenium/libs/react-manager/react.js +2 -0
- data/lib/proscenium/libs/stimulus-loading.js +83 -0
- data/lib/proscenium/log_subscriber.rb +1 -2
- data/lib/proscenium/middleware/base.rb +1 -1
- data/lib/proscenium/middleware/esbuild.rb +3 -5
- data/lib/proscenium/middleware.rb +7 -1
- data/lib/proscenium/{side_load/monkey.rb → monkey.rb} +16 -12
- data/lib/proscenium/phlex/{resolve_css_modules.rb → css_modules.rb} +6 -20
- data/lib/proscenium/phlex/page.rb +2 -2
- data/lib/proscenium/phlex/react_component.rb +27 -64
- data/lib/proscenium/phlex.rb +10 -29
- data/lib/proscenium/railtie.rb +20 -22
- data/lib/proscenium/react_componentable.rb +94 -0
- data/lib/proscenium/resolver.rb +37 -0
- data/lib/proscenium/side_load.rb +13 -72
- data/lib/proscenium/source_path.rb +15 -0
- data/lib/proscenium/utils.rb +13 -0
- data/lib/proscenium/version.rb +1 -1
- data/lib/proscenium/view_component/css_modules.rb +11 -0
- data/lib/proscenium/view_component/react_component.rb +15 -28
- data/lib/proscenium/view_component/sideload.rb +4 -0
- data/lib/proscenium/view_component.rb +8 -31
- data/lib/proscenium.rb +24 -68
- metadata +21 -58
- data/lib/proscenium/css_module/class_names_resolver.rb +0 -66
- data/lib/proscenium/css_module/resolver.rb +0 -76
- data/lib/proscenium/current.rb +0 -9
- data/lib/proscenium/esbuild/golib.rb +0 -97
- data/lib/proscenium/esbuild.rb +0 -32
- data/lib/proscenium/phlex/component_concerns.rb +0 -27
- data/lib/proscenium/side_load/ensure_loaded.rb +0 -25
- data/lib/proscenium/side_load/helper.rb +0 -25
- data/lib/proscenium/view_component/tag_builder.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ba51d67d2c6c2befac8704baeeb65b18d14991af344900edd9e187096f7108c
|
4
|
+
data.tar.gz: 7303432ccf8f03d18cfd76bf98a7e6ba81be067e2855f8cb92b0f150064ec9c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03c303f97cd7c7cb45e8261b11bd6e011277e52f427f59866c148a36a7d6bb72aef8b30a11bf6eea39fc3356454444d62bb814922bffedf0041e2d7ac3f77bdd
|
7
|
+
data.tar.gz: ede216dd5c30f4950b704f0f0b4eb6760bd336747794c8130d816654aed4cba73d9e9671f5d1173343c9ffcf424dcba75b808f085725a62206451ad70251df9d
|
data/README.md
CHANGED
@@ -1,31 +1,65 @@
|
|
1
1
|
# Proscenium - Modern client-side development for Rails
|
2
2
|
|
3
|
-
Proscenium treats your client-side code as first class citizens of your Rails app, and assumes a
|
4
|
-
"fast by default" internet. It bundles your JS, JSX and CSS in real time, on demand, and with zero
|
5
|
-
configuration.
|
3
|
+
Proscenium treats your client-side code as first class citizens of your Rails app, and assumes a "fast by default" internet. It bundles your JavaScript and CSS in real time, on demand, and with zero configuration.
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
-
|
5
|
+
**The highlights:**
|
6
|
+
|
7
|
+
- Fast real-time bundling, tree-shaking, code-splitting and minification of Javascript (.js,.jsx), Typescript (.ts,.tsx) and CSS (.css).
|
8
|
+
- NO JavaScript runtime needed - just the browser!
|
10
9
|
- NO build step or pre-compilation.
|
11
10
|
- NO additional process or server - Just run Rails!
|
12
11
|
- Deep integration with Rails.
|
13
|
-
-
|
14
|
-
-
|
15
|
-
- Automatically side load JS/TS/CSS for your layouts and views.
|
16
|
-
- Import from NPM, URLs, and locally.
|
12
|
+
- Automatically side-load your layouts, views, and partials.
|
13
|
+
- Import from NPM, URL's, and locally.
|
17
14
|
- Server-side import map support.
|
18
|
-
- CSS Modules.
|
19
|
-
- CSS mixins.
|
15
|
+
- CSS Modules & mixins.
|
20
16
|
- Source maps.
|
21
|
-
|
17
|
+
|
18
|
+
## Table of Contents
|
19
|
+
|
20
|
+
- [Getting Started](#getting-started)
|
21
|
+
- [Installation](#installation)
|
22
|
+
- [Client-Side Code Anywhere](#client-side-code-anywhere)
|
23
|
+
- [Side Loading](#side-loading)
|
24
|
+
- [Importing](#importing-assets)
|
25
|
+
- [URL Imports](#url-imports)
|
26
|
+
- [Local Imports](#local-imports)
|
27
|
+
- [Import Maps](#import-maps)
|
28
|
+
- [Source Maps](#source-maps)
|
29
|
+
- [SVG](#svg)
|
30
|
+
- [Environment Variables](#environment-variables)
|
31
|
+
- [i18n](#i18n)
|
32
|
+
- [JavaScript](#javascript)
|
33
|
+
- [Tree Shaking](#tree-shaking)
|
34
|
+
- [Code Splitting](#code-splitting)
|
35
|
+
- [JavaScript Caveats](#javascript-caveats)
|
36
|
+
- [CSS](#css)
|
37
|
+
- [Importing CSS from JavaScript](#importing-css-from-javascript)
|
38
|
+
- [CSS Modules](#css-modules)
|
39
|
+
- [CSS Mixins](#css-mixins)
|
40
|
+
- [CSS Caveats](#css-caveats)
|
41
|
+
- [Typescript](#typescript)
|
42
|
+
- [Typescript Caveats](#typescript-caveats)
|
43
|
+
- [JSX](#jsx)
|
44
|
+
- [JSON](#json)
|
45
|
+
- [Phlex Support](#phlex-support)
|
46
|
+
- [ViewComponent Support](#viewcomponent-support)
|
47
|
+
- [Cache Busting](#cache-busting)
|
48
|
+
- [rjs is back!](#rjs-is-back)
|
49
|
+
- [Included Paths](#included-paths)
|
50
|
+
- [Thanks](#thanks)
|
51
|
+
- [Development](#development)
|
22
52
|
|
23
53
|
## Getting Started
|
24
54
|
|
25
|
-
Getting started obviously depends on whether you are adding Proscenium to an existing Rails app, or creating a new
|
55
|
+
Getting started obviously depends on whether you are adding Proscenium to an existing Rails app, or creating a new one. So choose the appropriate guide below:
|
26
56
|
|
27
57
|
- [Getting Started with a new Rails app](https://github.com/joelmoss/proscenium/blob/master/docs/guides/new_rails_app.md)
|
28
|
-
- Getting Started with an existing Rails app
|
58
|
+
- Getting Started with an existing Rails app
|
59
|
+
- [Migrate from Sprockets](docs/guides/migrate_from_sprockets.md)
|
60
|
+
- Migrate from Propshaft *[Coming soon]*
|
61
|
+
- Migrate from Webpacker *[Coming soon]*
|
62
|
+
- [Render a React component with Proscenium](docs/guides/basic_react.md)
|
29
63
|
|
30
64
|
## Installation
|
31
65
|
|
@@ -53,48 +87,107 @@ Using the examples above...
|
|
53
87
|
- `app/components/menu_component.jsx` => `https://yourapp.com/app/components/menu_component.jsx`
|
54
88
|
- `config/properties.css` => `https://yourapp.com/config/properties.css`
|
55
89
|
|
56
|
-
|
90
|
+
## Side Loading
|
57
91
|
|
58
|
-
|
92
|
+
> Prior to **0.10.0**, only assets with the extension `.js`, `.ts` and `.css` were side loaded. From 0.10.0, all assets are side loaded, including `.jsx`, `.tsx`, and `.module.css`. Also partials were not side loaded prior to 0.10.0.
|
59
93
|
|
60
|
-
|
94
|
+
Proscenium is best experienced when you side load your assets.
|
61
95
|
|
62
|
-
|
63
|
-
|
96
|
+
### The Problem
|
97
|
+
|
98
|
+
With Rails you would typically declaratively load your JavaScript and CSS assets using the `javascript_include_tag` and `stylesheet_link_tag` helpers.
|
99
|
+
|
100
|
+
For example, you may have top-level "application" CSS located in a file at `/app/assets/application.css`. Likewise, you may have some global JavaScript located in a file at `/app/assets/application.js`.
|
101
|
+
|
102
|
+
You would manually and declaratively include those two files in your application layout, something like this:
|
103
|
+
|
104
|
+
```erb
|
105
|
+
<%# /app/views/layouts/application.html.erb %>
|
106
|
+
|
107
|
+
<!DOCTYPE html>
|
108
|
+
<html>
|
109
|
+
<head>
|
110
|
+
<title>Hello World</title>
|
111
|
+
<%= stylesheet_link_tag 'application' %> <!-- << Your app CSS -->
|
112
|
+
</head>
|
113
|
+
<body>
|
114
|
+
<%= yield %>
|
115
|
+
<%= javascript_include_tag 'application' %> <!-- << Your app JS -->
|
116
|
+
</body>
|
117
|
+
</html>
|
64
118
|
```
|
65
119
|
|
66
|
-
|
120
|
+
Now, you may have some CSS and JavaScript that is only required by a specific view and partial, so you would load that in your view (or layout), something like this:
|
67
121
|
|
68
|
-
|
69
|
-
|
122
|
+
```erb
|
123
|
+
<%# /app/views/users/index.html.erb %>
|
70
124
|
|
71
|
-
|
72
|
-
|
73
|
-
this:
|
125
|
+
<%= stylesheet_link_tag 'users' %>
|
126
|
+
<%= javascript_include_tag 'users' %>
|
74
127
|
|
75
|
-
|
128
|
+
<%# needed by the `users/_user.html.erb` partial %>
|
129
|
+
<%= javascript_include_tag '_user' %>
|
130
|
+
|
131
|
+
<% render @users %>
|
132
|
+
```
|
133
|
+
|
134
|
+
The main problem is that you have to keep track of all these assets, and make sure each is loaded by all the views that require them, but also avoid loading them when not needed. This can be a real pain, especially when you have a lot of views.
|
135
|
+
|
136
|
+
### The Solution
|
137
|
+
|
138
|
+
When side loading your JavaScript, Typescript and CSS with Proscenium, they are automatically included alongside your views, partials, layouts, and components, and only when needed.
|
139
|
+
|
140
|
+
Side loading works by looking for a JS/TS/CSS file with the same name as your view, partial, layout or component. For example, if you have a view at `app/views/users/index.html.erb`, then Proscenium will look for a JS/TS/CSS file at `app/views/users/index.js`, `app/views/users/index.ts` or `app/views/users/index.css`. If it finds one, it will include it in the HTML for that view.
|
141
|
+
|
142
|
+
JSX is also supported for JavaScript and Typescript. Simply use the `.jsx` or `.tsx` extension instead of `.js` or `.ts`.
|
143
|
+
|
144
|
+
### Usage
|
145
|
+
|
146
|
+
Simply create a JS and/or CSS file with the same name as any view, partial or layout.
|
147
|
+
|
148
|
+
Let's continue with our problem example above, where we have the following assets
|
149
|
+
|
150
|
+
- `/app/assets/application.css`
|
151
|
+
- `/app/assets/application.js`
|
152
|
+
- `/app/assets/users.css`
|
153
|
+
- `/app/assets/users.js`
|
154
|
+
- `/app/assets/user.js`
|
155
|
+
|
156
|
+
Your application layout is at `/app/views/layouts/application.hml.erb`, and the view that needs the users assets is at `/app/views/users/index.html.erb`, so move your assets JS and CSS alongside them:
|
157
|
+
|
158
|
+
- `/app/views/layouts/application.css`
|
159
|
+
- `/app/views/layouts/application.js`
|
160
|
+
- `/app/views/users/index.css`
|
161
|
+
- `/app/views/users/index.js`
|
162
|
+
- `/app/views/users/_user.js` (partial)
|
163
|
+
|
164
|
+
Now, in your layout and view, replace the `javascript_include_tag` and `stylesheet_link_tag` helpers with the `include_stylesheets` and `include_javascripts` helpers from Proscenium. Something like this:
|
165
|
+
|
166
|
+
```erb
|
76
167
|
<!DOCTYPE html>
|
77
168
|
<html>
|
78
169
|
<head>
|
79
170
|
<title>Hello World</title>
|
80
|
-
<%=
|
171
|
+
<%= include_stylesheets %>
|
81
172
|
</head>
|
82
173
|
<body>
|
83
174
|
<%= yield %>
|
84
|
-
<%=
|
175
|
+
<%= include_javascripts type: 'module', defer: true %>
|
85
176
|
</body>
|
86
177
|
</html>
|
87
178
|
```
|
88
179
|
|
89
|
-
|
90
|
-
|
180
|
+
> NOTE that Proscenium is desiged to work with modern JavaAscript, and assumes [ESModules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) are used everywhere. This is why the `type` attribute is set to `module` in the example above. If you are not using ESModules, then you can omit the `type` attribute.
|
181
|
+
|
182
|
+
On each page request, Proscenium will check if your views, layouts and partials have a JS/TS/CSS file of the same name, and then include them wherever your placed the `include_stylesheets` and `include_javascripts` helpers.
|
91
183
|
|
92
|
-
|
93
|
-
to `false`.
|
184
|
+
Now you never have to remember to include your assets again. Just create them alongside your views, partials and layouts, and Proscenium will take care of the rest.
|
94
185
|
|
95
|
-
|
186
|
+
Side loading is enabled by default, but you can disable it by setting `config.proscenium.side_load` to `false` in your `/config/application.rb`.
|
96
187
|
|
97
|
-
|
188
|
+
## Importing Assets
|
189
|
+
|
190
|
+
Proscenium supports importing JS, JSX, TS, TSX, CSS and SVG from NPM, by URL, your local app, and even from Ruby Gems.
|
98
191
|
|
99
192
|
Imported files are bundled together in real time. So no build step or pre-compilation is needed.
|
100
193
|
|
@@ -134,9 +227,13 @@ import utils from '/lib/utils'
|
|
134
227
|
import constants from './constants'
|
135
228
|
```
|
136
229
|
|
137
|
-
## Import
|
230
|
+
## Import Maps
|
231
|
+
|
232
|
+
> **[WIP]**
|
233
|
+
|
234
|
+
[Import maps](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) for both JS and CSS is supported out of the box, and works with no regard to the browser being used. This is because the import map is parsed and resolved by Proscenium on the server, instead of by the browser. This is faster, and also allows you to use import maps in browsers that do not support them yet.
|
138
235
|
|
139
|
-
|
236
|
+
If you are not familiar with import maps, think of them as a way to define aliases.
|
140
237
|
|
141
238
|
Just create `config/import_map.json` and specify the imports you want to use. For example:
|
142
239
|
|
@@ -166,7 +263,7 @@ and for CSS...
|
|
166
263
|
@import '@radix-ui/colors/blue.css';
|
167
264
|
```
|
168
265
|
|
169
|
-
You can also write your import map in
|
266
|
+
You can also write your import map in JavaScript instead of JSON. So instead of `config/import_map.json`, create `config/import_map.js`, and define an anonymous function. This function accepts a single `environment` argument.
|
170
267
|
|
171
268
|
```js
|
172
269
|
env => ({
|
@@ -176,21 +273,89 @@ env => ({
|
|
176
273
|
})
|
177
274
|
```
|
178
275
|
|
179
|
-
##
|
276
|
+
## Source Maps
|
277
|
+
|
278
|
+
Source maps can make it easier to debug your code. They encode the information necessary to translate from a line/column offset in a generated output file back to a line/column offset in the corresponding original input file. This is useful if your generated code is sufficiently different from your original code (e.g. your original code is TypeScript or you enabled minification). This is also useful if you prefer looking at individual files in your browser's developer tools instead of one big bundled file.
|
279
|
+
|
280
|
+
Source map output is supported for both JavaScript and CSS. Each file is appended with the link to the source map. For example:
|
281
|
+
|
282
|
+
```js
|
283
|
+
//# sourceMappingURL=/app/views/layouts/application.js.map
|
284
|
+
```
|
180
285
|
|
181
|
-
|
286
|
+
Your browsers dev tools should pick this up and automatically load the source map when and where needed.
|
287
|
+
|
288
|
+
## SVG
|
289
|
+
|
290
|
+
You can import SVG from JS(X), which will bundle the SVG source code. Additionally, if importing from JSX or TSX, the SVG source code will be rendered as a JSX/TSX component.
|
182
291
|
|
183
292
|
## Environment Variables
|
184
293
|
|
185
|
-
|
294
|
+
> Available in `>=0.10.0`
|
295
|
+
|
296
|
+
You can define and access any environment variable from your JavaScript and Typescript under the `proscenium.env` namespace.
|
297
|
+
|
298
|
+
For performance and security reasons you must declare the environment variable names that you wish to expose in your `config/application.rb` file.
|
299
|
+
|
300
|
+
```ruby
|
301
|
+
config.proscenium.env_vars = Set['API_KEY', 'SOME_SECRET_VARIABLE']
|
302
|
+
config.proscenium.env_vars << 'ANOTHER_API_KEY'
|
303
|
+
```
|
304
|
+
|
305
|
+
This assumes that the environment variable of the same name has already been defined. If not, you will need to define it yourself either in your code using Ruby's `ENV` object, or in your shell.
|
306
|
+
|
307
|
+
These declared environment variables will be replaced with constant expressions, allowing you to use this like this:
|
308
|
+
|
309
|
+
```js
|
310
|
+
console.log(proscenium.env.RAILS_ENV) // console.log("development")
|
311
|
+
console.log(proscenium.env.RAILS_ENV === 'development') // console.log(true)
|
312
|
+
```
|
313
|
+
|
314
|
+
The `RAILS_ENV` and `NODE_ENV` environment variables will always automatically be declared for you.
|
315
|
+
|
316
|
+
In addition to this, Proscenium also provides a `process.env.NODE_ENV` variable, which is set to the same value as `proscenium.env.RAILS_ENV`. It is provided to support the community's existing tooling, which often relies on this variable.
|
317
|
+
|
318
|
+
Environment variables are particularly powerful in aiding [tree shaking](#tree-shaking).
|
319
|
+
|
320
|
+
```js
|
321
|
+
function start() {
|
322
|
+
console.log("start")
|
323
|
+
}
|
324
|
+
function doSomethingDangerous() {
|
325
|
+
console.log("resetDatabase")
|
326
|
+
}
|
327
|
+
|
328
|
+
proscenium.env.RAILS_ENV === "development" && doSomethingDangerous()
|
329
|
+
|
330
|
+
start()
|
331
|
+
```
|
332
|
+
|
333
|
+
In development the above code will be transformed into the following code, discarding the definition, and call to`doSomethingDangerous()`.
|
186
334
|
|
187
335
|
```js
|
188
|
-
|
336
|
+
function start() {
|
337
|
+
console.log("start")
|
338
|
+
}
|
339
|
+
start()
|
340
|
+
```
|
341
|
+
|
342
|
+
Please note that for security reasons environment variables are not replaced in URL imports.
|
343
|
+
|
344
|
+
An undefined environment variable will be replaced with `undefined`.
|
345
|
+
|
346
|
+
```js
|
347
|
+
console.log(proscenium.env.UNKNOWN) // console.log((void 0).UNKNOWN)
|
189
348
|
```
|
190
349
|
|
191
|
-
|
350
|
+
This means that code that relies on this will not be tree shaken. You can work around this by using the [optional chaining operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining):
|
192
351
|
|
193
|
-
|
352
|
+
```js
|
353
|
+
if (typeof proscenium.env?.UNKNOWN !== "undefined") {
|
354
|
+
// do something if UNKNOWN is defined
|
355
|
+
}
|
356
|
+
```
|
357
|
+
|
358
|
+
## i18n
|
194
359
|
|
195
360
|
Basic support is provided for importing your Rails locale files from `config/locales/*.yml`, exporting them as JSON.
|
196
361
|
|
@@ -226,6 +391,48 @@ function one() {
|
|
226
391
|
one();
|
227
392
|
```
|
228
393
|
|
394
|
+
### Code Splitting
|
395
|
+
|
396
|
+
> Available in `>=0.10.0`.
|
397
|
+
|
398
|
+
[Side loaded](#side-loading) assets are automatically code split. This means that if you have a file that is imported and used imported several times, and by different files, it will be split off into a separate file.
|
399
|
+
|
400
|
+
As an example:
|
401
|
+
|
402
|
+
```js
|
403
|
+
// /lib/son.js
|
404
|
+
import father from "./father";
|
405
|
+
|
406
|
+
father() + " and Son";
|
407
|
+
```
|
408
|
+
|
409
|
+
```js
|
410
|
+
// /lib/daughter.js
|
411
|
+
import father from "./father";
|
412
|
+
|
413
|
+
father() + " and Daughter";
|
414
|
+
```
|
415
|
+
|
416
|
+
```js
|
417
|
+
// /lib/father.js
|
418
|
+
export default () => "Father";
|
419
|
+
```
|
420
|
+
|
421
|
+
Both `son.js` and `daughter.js` import `father.js`, so both son and daughter would usually include a copy of father, resulting in duplicated code and larger bundle sizes.
|
422
|
+
|
423
|
+
If these files are side loaded, then `father.js` will be split off into a separate file or chunk, and only downloaded once.
|
424
|
+
|
425
|
+
- Code shared between multiple entry points is split off into a separate shared file that both entry points import. That way if the user first browses to one page and then to another page, they don't have to download all of the JavaScript for the second page from scratch if the shared part has already been downloaded and cached by their browser.
|
426
|
+
|
427
|
+
- Code referenced through an asynchronous `import()` expression will be split off into a separate file and only loaded when that expression is evaluated. This allows you to improve the initial download time of your app by only downloading the code you need at startup, and then lazily downloading additional code if needed later.
|
428
|
+
|
429
|
+
- Without code splitting, an import() expression becomes `Promise.resolve().then(() => require())` instead. This still preserves the asynchronous semantics of the expression but it means the imported code is included in the same bundle instead of being split off into a separate file.
|
430
|
+
|
431
|
+
Code splitting is enabled by default. You can disable it by setting the `code_splitting` configuration option to `false` in your application's `/config/application.rb`:
|
432
|
+
```ruby
|
433
|
+
config.proscenium.code_splitting = false
|
434
|
+
```
|
435
|
+
|
229
436
|
### JavaScript Caveats
|
230
437
|
|
231
438
|
There are a few important caveats as far as JavaScript is concerned. These are [detailed on the esbuild site](https://esbuild.github.io/content-types/#javascript-caveats).
|
@@ -238,7 +445,7 @@ Note that by default, Proscenium's output will take advantage of all modern CSS
|
|
238
445
|
|
239
446
|
The new CSS nesting syntax is supported, and transformed into non-nested CSS for older browsers.
|
240
447
|
|
241
|
-
### Importing from JavaScript
|
448
|
+
### Importing CSS from JavaScript
|
242
449
|
|
243
450
|
You can also import CSS from JavaScript. When you do this, Proscenium will automatically append each stylesheet to the document's head as a `<link>` element.
|
244
451
|
|
@@ -252,34 +459,74 @@ export let Button = ({ text }) => {
|
|
252
459
|
|
253
460
|
### CSS Modules
|
254
461
|
|
255
|
-
Proscenium implements a subset of [CSS Modules](https://github.com/css-modules/css-modules). It supports the `:local` and `:global` keywords, but not the `composes` property.
|
462
|
+
Proscenium implements a subset of [CSS Modules](https://github.com/css-modules/css-modules). It supports the `:local` and `:global` keywords, but not the `composes` property. (it is recommended that you use mixins instead of `composes`, as they will work everywhere, even in plain CSS files.)
|
256
463
|
|
257
|
-
Give any CSS file a `.module.css` extension, and Proscenium will
|
464
|
+
Give any CSS file a `.module.css` extension, and Proscenium will treat it as a CSS Module, transforming all class names with a suffix unique to the file.
|
258
465
|
|
259
466
|
```css
|
260
|
-
.
|
261
|
-
|
467
|
+
.title {
|
468
|
+
font-size: 20em;
|
262
469
|
}
|
263
470
|
```
|
264
471
|
|
265
472
|
The above input produces:
|
266
473
|
|
267
474
|
```css
|
268
|
-
.
|
269
|
-
|
475
|
+
.title-5564cdbb {
|
476
|
+
font-size: 20em;
|
270
477
|
}
|
271
478
|
```
|
272
479
|
|
273
|
-
|
480
|
+
You now have a unique class name that you can use pretty much anywhere.
|
481
|
+
|
482
|
+
#### In your Views
|
483
|
+
|
484
|
+
You can reference CSS modules from your Rails views, partials, and layouts using the `css_module` helper, which accepts one or more class names, and will return the equivilent CSS module names - the class name with the unique suffix appended.
|
485
|
+
|
486
|
+
With [side-loading](#side-loading) setup, you can use the `css_module` helper as follows.
|
487
|
+
|
488
|
+
```erb
|
489
|
+
<div>
|
490
|
+
<h1 class="<%= css_module :hello_title %>">Hello World</h1>
|
491
|
+
<p class="<%= css_module :body, paragraph: %>">
|
492
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
493
|
+
</p>
|
494
|
+
</div>
|
495
|
+
```
|
496
|
+
|
497
|
+
`css_module` accepts multiple class names, and will return a space-separated string of transformed CSS module names.
|
498
|
+
|
499
|
+
```ruby
|
500
|
+
css_module :my_module_name
|
501
|
+
# => "my_module_name-ABCD1234"
|
502
|
+
```
|
503
|
+
|
504
|
+
You can even reference a class from any CSS file by passing the URL path to the file, as a prefix to the class name. Doing so will automatically [side load](#side-loading) the stylesheet.
|
505
|
+
|
506
|
+
```ruby
|
507
|
+
css_module '/app/components/button.css@big_button'
|
508
|
+
# => "big_button"
|
509
|
+
```
|
510
|
+
|
511
|
+
It also supports NPM packages (already installed in /node_modules):
|
512
|
+
|
513
|
+
```ruby
|
514
|
+
css_module 'mypackage/button@big_button'
|
515
|
+
# => "big_button"
|
516
|
+
```
|
517
|
+
|
518
|
+
#### In your JavaScript
|
519
|
+
|
520
|
+
Importing a CSS module from JS will automatically append the stylesheet to the document's head. And the result of the import will be an object of CSS class to module names.
|
274
521
|
|
275
522
|
```js
|
276
523
|
import styles from './styles.module.css'
|
277
|
-
// styles == { header: '
|
524
|
+
// styles == { header: 'header-5564cdbb' }
|
278
525
|
```
|
279
526
|
|
280
|
-
It is important to note that the exported object of CSS module names is actually a Proxy object. So destructuring the object will not work. Instead, you must access the properties directly.
|
527
|
+
It is important to note that the exported object of CSS module names is actually a JavaScript [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) object. So destructuring the object will not work. Instead, you must access the properties directly.
|
281
528
|
|
282
|
-
Also, importing a CSS module
|
529
|
+
Also, importing a CSS module into another CSS module will result in the same digest string for all classes.
|
283
530
|
|
284
531
|
### CSS Mixins
|
285
532
|
|
@@ -377,13 +624,116 @@ console.log(version)
|
|
377
624
|
|
378
625
|
## Phlex Support
|
379
626
|
|
380
|
-
|
627
|
+
[Phlex](https://www.phlex.fun/) is a framework for building fast, reusable, testable views in pure Ruby. Proscenium works perfectly with Phlex, with support for side-loading, CSS modules, and more. Simply write your Phlex classes and inherit from `Proscenium::Phlex`.
|
628
|
+
|
629
|
+
```ruby
|
630
|
+
class MyView < Proscenium::Phlex
|
631
|
+
def template
|
632
|
+
h1 { 'Hello World' }
|
633
|
+
end
|
634
|
+
end
|
635
|
+
```
|
636
|
+
|
637
|
+
### Side-loading
|
638
|
+
|
639
|
+
Any Phlex class that inherits `Proscenium::Phlex` will automatically be [side-loaded](#side-loading).
|
640
|
+
|
641
|
+
### CSS Modules
|
642
|
+
|
643
|
+
[CSS Modules](#css-modules) are fully supported in Phlex classes, with access to the [`css_module` helper](#in-your-views) if you need it. However, there is a better and more seemless way to reference CSS module classes in your Phlex classes.
|
644
|
+
|
645
|
+
Within your Phlex classes, any class names that begin with `@` will be treated as a CSS module class.
|
646
|
+
|
647
|
+
```ruby
|
648
|
+
# /app/views/users/show_view.rb
|
649
|
+
class Users::ShowView < Proscenium::Phlex
|
650
|
+
def template
|
651
|
+
h1 class: :@user_name do
|
652
|
+
@user.name
|
653
|
+
end
|
654
|
+
end
|
655
|
+
end
|
656
|
+
```
|
657
|
+
|
658
|
+
```css
|
659
|
+
/* /app/views/users/show_view.module.css */
|
660
|
+
.userName {
|
661
|
+
color: red;
|
662
|
+
font-size: 50px;
|
663
|
+
}
|
664
|
+
```
|
665
|
+
|
666
|
+
In the above `Users::ShowView` Phlex class, the `@user_name` class will be resolved to the `userName` class in the `users/show_view.module.css` file.
|
667
|
+
|
668
|
+
The view above will be rendered something like this:
|
669
|
+
|
670
|
+
```html
|
671
|
+
<h1 class="user_name-ABCD1234"></h1>
|
672
|
+
```
|
673
|
+
|
674
|
+
You can of course continue to reference regular class names in your view, and they will be passed through as is. This will allow you to mix and match CSS modules and regular CSS classes in your views.
|
675
|
+
|
676
|
+
```ruby
|
677
|
+
# /app/views/users/show_view.rb
|
678
|
+
class Users::ShowView < Proscenium::Phlex
|
679
|
+
def template
|
680
|
+
h1 class: :[@user_name, :title] do
|
681
|
+
@user.name
|
682
|
+
end
|
683
|
+
end
|
684
|
+
end
|
685
|
+
```
|
686
|
+
|
687
|
+
```html
|
688
|
+
<h1 class="user_name-ABCD1234 title">Joel Moss</h1>
|
689
|
+
```
|
381
690
|
|
382
691
|
## ViewComponent Support
|
383
692
|
|
384
|
-
|
693
|
+
[ViewComponent](https://viewcomponent.org/) iA framework for creating reusable, testable & encapsulated view components, built to integrate seamlessly with Ruby on Rails. Proscenium works perfectly with ViewComponent, with support for side-loading, CSS modules, and more. Simply write your ViewComponent classes and inherit from `Proscenium::ViewComponent`.
|
694
|
+
|
695
|
+
```ruby
|
696
|
+
class MyView < Proscenium::ViewComponent
|
697
|
+
def call
|
698
|
+
tag.h1 'Hello World'
|
699
|
+
end
|
700
|
+
end
|
701
|
+
```
|
702
|
+
|
703
|
+
### Side-loading
|
704
|
+
|
705
|
+
Any ViewComponent class that inherits `Proscenium::ViewComponent` will automatically be [side-loaded](#side-loading).
|
706
|
+
|
707
|
+
### CSS Modules
|
708
|
+
|
709
|
+
[CSS Modules](#css-modules) are fully supported in ViewComponent classes, with access to the [`css_module` helper](#in-your-views) if you need it.
|
385
710
|
|
386
|
-
|
711
|
+
```ruby
|
712
|
+
# /app/components/user_component.rb
|
713
|
+
class UserComponent < Proscenium::ViewComponent
|
714
|
+
def template
|
715
|
+
div.h1 @user.name, class: css_module(:user_name)
|
716
|
+
end
|
717
|
+
end
|
718
|
+
```
|
719
|
+
|
720
|
+
```css
|
721
|
+
/* # /app/components/user_component.module.css */
|
722
|
+
.userName {
|
723
|
+
color: red;
|
724
|
+
font-size: 50px;
|
725
|
+
}
|
726
|
+
```
|
727
|
+
|
728
|
+
The view above will be rendered something like this:
|
729
|
+
|
730
|
+
```html
|
731
|
+
<h1 class="user_name-ABCD1234">Joel Moss</h1>
|
732
|
+
```
|
733
|
+
|
734
|
+
## Cache Busting
|
735
|
+
|
736
|
+
> *COMING SOON*
|
387
737
|
|
388
738
|
By default, all assets are not cached by the browser. But if in production, you populate the `REVISION` env variable, all CSS and JS URL's will be appended with its value as a query string, and the `Cache-Control` response header will be set to `public` and a max-age of 30 days.
|
389
739
|
|
@@ -403,7 +753,7 @@ The cache is set with a `max-age` of 30 days. You can customise this with the `c
|
|
403
753
|
Rails.application.config.proscenium.cache_max_age = 12.months.to_i
|
404
754
|
```
|
405
755
|
|
406
|
-
## rjs is back
|
756
|
+
## rjs is back
|
407
757
|
|
408
758
|
Proscenium brings back RJS! Any path ending in .rjs will be served from your Rails app. This allows you to import server rendered javascript.
|
409
759
|
|
@@ -411,9 +761,19 @@ Proscenium brings back RJS! Any path ending in .rjs will be served from your Rai
|
|
411
761
|
|
412
762
|
*docs needed*
|
413
763
|
|
414
|
-
##
|
764
|
+
## Included Paths
|
765
|
+
|
766
|
+
By default, Proscenium will serve files ending with any of these extension: `js,mjs,ts,css,jsx,tsx`, and only from `app/assets`, `config`, `app/views`, `lib` and `node_modules` directories.
|
767
|
+
|
768
|
+
However, you can customise these paths with the `include_path` config option...
|
769
|
+
|
770
|
+
```ruby
|
771
|
+
Rails.application.config.proscenium.include_paths << 'app/components'
|
772
|
+
```
|
773
|
+
|
774
|
+
## Thanks
|
415
775
|
|
416
|
-
HUGE thanks go to [Evan Wallace](https://github.com/evanw) and his amazing [esbuild](https://esbuild.github.io/) project. Proscenium would not be possible without it, and it is esbuild that makes this so fast and efficient.
|
776
|
+
HUGE thanks 🙏 go to [Evan Wallace](https://github.com/evanw) and his amazing [esbuild](https://esbuild.github.io/) project. Proscenium would not be possible without it, and it is esbuild that makes this so fast and efficient.
|
417
777
|
|
418
778
|
Because Proscenium uses esbuild extensively, some of these docs are taken directly from the esbuild docs, with links back to the [esbuild site](https://esbuild.github.io/) where appropriate.
|
419
779
|
|
@@ -430,7 +790,7 @@ bundle exec rake compile:local
|
|
430
790
|
We have tests for both Ruby and Go. To run the Ruby tests:
|
431
791
|
|
432
792
|
```bash
|
433
|
-
bundle exec
|
793
|
+
bundle exec sus
|
434
794
|
```
|
435
795
|
|
436
796
|
To run the Go tests:
|
@@ -447,7 +807,7 @@ go test ./internal/builder -bench=. -run="^$" -count=10 -benchmem
|
|
447
807
|
|
448
808
|
## Contributing
|
449
809
|
|
450
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/joelmoss/proscenium
|
810
|
+
Bug reports and pull requests are welcome on GitHub at <https://github.com/joelmoss/proscenium>. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/joelmoss/proscenium/blob/master/CODE_OF_CONDUCT.md).
|
451
811
|
|
452
812
|
## License
|
453
813
|
|