Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change vendor.js to app.js in documentation #700

Merged
merged 1 commit into from
Jan 24, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions tests/dummy/app/templates/docs/faq/routing-and-asset-loading.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ This way when building for Electron, the app will be configured to use the hash

## Asset loading

Ember apps typically load their assets using relative URLs with absolute paths, e.g. `<script src="/assets/vendor.js"></script>` or `<img src="/img/logo.jpg">`. The browser combines these with the current location to generate the URL from which to load the asset. So if our current URL is `http://my-app.com`, our example assets URLs would resolve to `http://my-app.com/assets/vendor.js` and `http://my-app.com/img/logo.jpg`. Even if our current URL is `http://my-app.com/my-route`, they will resolve to those same URLs, because of the fact that the asset URL paths are absolute, i.e. start with `/`, so when combined with the current URL, the asset path replaces the URL path, rather than being appended to it.
Ember apps typically load their assets using relative URLs with absolute paths, e.g. `<script src="/assets/app.js"></script>` or `<img src="/img/logo.jpg">`. The browser combines these with the current location to generate the URL from which to load the asset. So if our current URL is `http://my-app.com`, our example assets URLs would resolve to `http://my-app.com/assets/app.js` and `http://my-app.com/img/logo.jpg`. Even if our current URL is `http://my-app.com/my-route`, they will resolve to those same URLs, because of the fact that the asset URL paths are absolute, i.e. start with `/`, so when combined with the current URL, the asset path replaces the URL path, rather than being appended to it.

With `file:` URLs, though, this won't work because, following those same rules, combining `file:///Users/me/projects/my-app/electron-app/ember-dist/index.html` with `/assets/vendor.js` will result in `file:///assets/vendor.js`, not `file:///Users/me/projects/my-app/electron-app/ember-dist/assets/vendor.js`, which is where `vendor.js` actually lives. HTML loaded from the filesystem typically uses relative URLs to get around this, i.e. if we had `<script src="assets/vendor.js"></script>` or `<img src="img/logo.jpg">` (note that there are no leading `/`s), then the paths would be interpreted as relative to the current directory, and would resolve to the correct `file:` URLs.
With `file:` URLs, though, this won't work because, following those same rules, combining `file:///Users/me/projects/my-app/electron-app/ember-dist/index.html` with `/assets/app.js` will result in `file:///assets/app.js`, not `file:///Users/me/projects/my-app/electron-app/ember-dist/assets/app.js`, which is where `app.js` actually lives. HTML loaded from the filesystem typically uses relative URLs to get around this, i.e. if we had `<script src="assets/app.js"></script>` or `<img src="img/logo.jpg">` (note that there are no leading `/`s), then the paths would be interpreted as relative to the current directory, and would resolve to the correct `file:` URLs.

### Javascript and CSS

For `vendor.js` and other scripts and CSS loaded out of `index.html`, we have a nice solution for making the URL paths relative. The Ember app's `index.html` specifies them using a `rootURL` template parameter, e.g. `<script src="{{rootURL}}assets/vendor.js"></script>`, which is resolved during the Ember build. The default `rootURL` for Ember apps is `/`, so it would end up being `<script src="/assets/vendor.js"></script>`. But we can set the `rootURL` to `''`, causing it to end up being `<script src="assets/vendor.js"></script>` -- a relative path, which is exactly what we want. This is why `ember-electron`'s blueprint configures the application's `config/environment.js` with the following:
For `app.js` and other scripts and CSS loaded out of `index.html`, we have a nice solution for making the URL paths relative. The Ember app's `index.html` specifies them using a `rootURL` template parameter, e.g. `<script src="{{rootURL}}assets/app.js"></script>`, which is resolved during the Ember build. The default `rootURL` for Ember apps is `/`, so it would end up being `<script src="/assets/app.js"></script>`. But we can set the `rootURL` to `''`, causing it to end up being `<script src="assets/app.js"></script>` -- a relative path, which is exactly what we want. This is why `ember-electron`'s blueprint configures the application's `config/environment.js` with the following:

```javascript
rootURL: process.env.EMBER_CLI_ELECTRON ? '' : '/',
```

There is an additional wrinkle when running tests. Since Ember puts the `index.html` used for tests at `tests/index.html`, it actually needs assets paths that look like `../assets/vendor.js`. However, `ember-cli` ([clean-base-url](https://github.com/ember-cli/clean-base-url) actually) forces a non-empty `rootURL` to start with `/`, so `ember-electron` uses the broccoli pipeline to modify these URLs in `tests/index.html` to start with `../`.
There is an additional wrinkle when running tests. Since Ember puts the `index.html` used for tests at `tests/index.html`, it actually needs assets paths that look like `../assets/app.js`. However, `ember-cli` ([clean-base-url](https://github.com/ember-cli/clean-base-url) actually) forces a non-empty `rootURL` to start with `/`, so `ember-electron` uses the broccoli pipeline to modify these URLs in `tests/index.html` to start with `../`.

### Other assets (images, fonts, etc.)

Expand All @@ -52,7 +52,7 @@ This is not perfect -- there is a concievable case where it could do the wrong t

### Source maps

One might observe that the solution for images, fonts, etc., could also apply to the Javascript and CSS, and wonder why we need both solutions. The answer is source maps. Unfortunately when the Chromium developer tools load source maps, it is not intercept-able by the Electron `protocol` module, and the developer tools are not aware of any intercepting that happens in the main process. So if we left the leading `/` on the script tags, e.g. `<script src="/assets/vendor.js"></script>`, then when the developer tools sees the `sourceMappingURL=vendor.map` at the end of `vendor.js` it will treat `vendor.map` as a path that is relative to where it thinks the script was loaded from, i.e. `/assets/vendor.js`, so it will try to load it from `/assets/vendor.map`. Since this request isn't intercept-able, the source maps will fail to load. So to make source maps work, we really need to load the Javascript and CSS files from relative URLs, and since we cannot easily rewrite the other assets' URLs to be relative, we need two different solutions for the two different flavors of assets.
One might observe that the solution for images, fonts, etc., could also apply to the Javascript and CSS, and wonder why we need both solutions. The answer is source maps. Unfortunately when the Chromium developer tools load source maps, it is not intercept-able by the Electron `protocol` module, and the developer tools are not aware of any intercepting that happens in the main process. So if we left the leading `/` on the script tags, e.g. `<script src="/assets/app.js"></script>`, then when the developer tools sees the `sourceMappingURL=app.map` at the end of `app.js` it will treat `app.map` as a path that is relative to where it thinks the script was loaded from, i.e. `/assets/app.js`, so it will try to load it from `/assets/app.map`. Since this request isn't intercept-able, the source maps will fail to load. So to make source maps work, we really need to load the Javascript and CSS files from relative URLs, and since we cannot easily rewrite the other assets' URLs to be relative, we need two different solutions for the two different flavors of assets.

## Alternatives

Expand Down Expand Up @@ -81,7 +81,7 @@ fingerprint: {
}
```

This fixes all the asset paths to load into the browser, but leaves sourcemaps broken. The reason is that `broccoli-asset-rev` also rewrites source map URLs expecting them to be absolute. So if `prepend` is `http://cdn.com/`, then it would expect `vendor.map` to be at `http://cdn.com/assets/vendor-<hash>.map`, and would rewrite the `sourceMappingURL=vendor.map` at the end of `vendor.js` to be `sourceMappingURL=http://cdn.com/assets/vendor-<hash>.map`. This is fine for prepending absolute URLs, but if we prepend `./`, then it ends up rewriting the source map URL as `sourceMappingURL=./assets/vendor-<hash>.map`. But since both `vendor-<hash>.js` and `vendor-<hash>.map` end up in the same directory, and the `sourceMappingURL` is interpreted relative to where `vendor.js` is, it resolves to `.../ember-dist/assets/assets/vendor-<hash>.map`. `broccoli-asset-rev` simply doesn't expect or handle relative `prepend` URLs.
This fixes all the asset paths to load into the browser, but leaves sourcemaps broken. The reason is that `broccoli-asset-rev` also rewrites source map URLs expecting them to be absolute. So if `prepend` is `http://cdn.com/`, then it would expect `app.map` to be at `http://cdn.com/assets/app-<hash>.map`, and would rewrite the `sourceMappingURL=app.map` at the end of `app.js` to be `sourceMappingURL=http://cdn.com/assets/app-<hash>.map`. This is fine for prepending absolute URLs, but if we prepend `./`, then it ends up rewriting the source map URL as `sourceMappingURL=./assets/app-<hash>.map`. But since both `app-<hash>.js` and `app-<hash>.map` end up in the same directory, and the `sourceMappingURL` is interpreted relative to where `app.js` is, it resolves to `.../ember-dist/assets/assets/app-<hash>.map`. `broccoli-asset-rev` simply doesn't expect or handle relative `prepend` URLs.

This could potentially be fixed by broccoli'ing the map files into `assets/assets`, or using the broccoli pipeline to rewrite the `assets/assets/` to just be `assets/`, but then we're kinda layering kludges, and it really doesn't seem like the way to go. It can also be partially fixed by changing the fingerprint config to

Expand Down