diff --git a/libs/scully-plugin-flash-prevention/README.md b/libs/scully-plugin-flash-prevention/README.md index aad1443c5..75d178b64 100644 --- a/libs/scully-plugin-flash-prevention/README.md +++ b/libs/scully-plugin-flash-prevention/README.md @@ -1,7 +1,102 @@ -# scully-plugin-flash-prevention +# ScullyPluginFlashPrevention -This library was generated with [Nx](https://nx.dev). +The `scully-plugin-flash-prevention` is a postRenderer that helps you hide any flashes that your +app may be experiencing once you add Scully to your project. -## Running unit tests +After adding Scully, your app will appear instantly because the pre-rendered HTML and CSS is +immediately available. After appearing instantly, the JavaScript and CSS files will download and +then your Angular app will bootstrap (init). When it bootstraps, the pre-rendered version may +disappear for a moment, and then once the app is ready, the view will re-appear. This +disappearing-then-appearing is very normal for apps that are pre-rendered on a server. This +project is to prevent that. -Run `ng test scully-plugin-flash-prevention` to execute the unit tests via [Jest](https://jestjs.io). +This project shows the pre-rendered copy of your app until your app is fully render and the +flash is over. It then shows your app and deletes the copy. + +### How it works + +Before this plugin, you app would pre-render and then save to file, like this: + +```html + + // The entire content of your app here + +``` + +After this plugin, you will see the following in your pre-rendered template: + +```html + + + // The entire content of your app here + +``` + +This `app-root-scully` will be the pre-rendered copy of your app. Prior to your app being +rendered fully, `app-root` will be hidden and `app-root-scully` will be displayed. Once your +app has fully bootstrapped, `app-root-scully` will be hidden and then 100ms later removed +from the DOM. The mechanism that shows and hides these two is CSS. There is some CSS added +during the Scully build that looks like the following: + +```css +body:not(.loaded) app-root { + display: none; +} +body.loaded app-root-scully { + display: inherit; +} +``` + +Once the app has been fully loaded, the `loaded` class is added to the `` tag. + +And that's how it all works!!! + +## Getting Started + +**1 -** Install the package: `npm install -D scully-plugin-flash-prevention` + +**2 -** Add the postRenderer to your `scully.config`: + +```javascript +// Add this line to your imports +const { getFlashPreventionPlugin } = require('scully-plugin-flash-prevention'); + +// Add the following to your `scully.config.postRenderers` +exports.config = { + ... + postRenderers : [getFlashPreventionPlugin({appRootSelector: 'custom-app-root'})], + ... +} +``` + +You only need to pass the `{appRootSelector: 'custom-app-root'}` if your app has a selector other +than `app-root`. It is defaulted to `app-root`. + +**3 -** Update `app.module` to include `alwaysMonitor` in the `ScullyLibModule.forRoot` call. + +```typescript +ScullyLibModule.forRoot({ + useTransferState: true, + alwaysMonitor: true, <-- Add this line to your `app.module.ts` +}); +``` + +**4 -** Apply any styles from `app-root` to `app-root-scully` as well. Any styles that are in your +`app.component.(css|scss|less)` need to be applied to the copy of your app that was made. This means +that you need to possibly move any styles that apply to the `app-root` specifically, and put them +in a location where you can also make those styles apply to `app-root-scully` as well. See here: + +```css +// BEFORE +app-root { + ... some styles; +} + +// AFTER +app-root, +app-root-scully { + ... some styles; +} +``` + +That's all it takes to get set up. diff --git a/libs/scully-plugin-flash-prevention/package.json b/libs/scully-plugin-flash-prevention/package.json index 1082e75fe..ab5c3d12c 100644 --- a/libs/scully-plugin-flash-prevention/package.json +++ b/libs/scully-plugin-flash-prevention/package.json @@ -1,6 +1,6 @@ { "name": "scully-plugin-flash-prevention", - "version": "0.0.37", + "version": "0.0.38", "peerDependencies": { "@scullyio/scully": "^0.0.78" }, diff --git a/libs/scully-plugin-flash-prevention/src/lib/flash-prevention.plugin.ts b/libs/scully-plugin-flash-prevention/src/lib/flash-prevention.plugin.ts index 3b518ae9d..eded61f6d 100644 --- a/libs/scully-plugin-flash-prevention/src/lib/flash-prevention.plugin.ts +++ b/libs/scully-plugin-flash-prevention/src/lib/flash-prevention.plugin.ts @@ -4,6 +4,7 @@ import { appendToHead } from './utils'; let AppRootSelector = 'app-root'; let LoadedClass = 'loaded'; +let DisplayType = 'inherit'; const FlashPrevention = 'ScullyPluginFlashPrevention'; const AppRootAttrsBlacklist = ['_nghost', 'ng-version']; const MockRootAttrsBlacklist = []; @@ -14,6 +15,7 @@ registerPlugin('router', FlashPrevention, async ur => [{ route: ur }]); interface FlashPreventionPluginOptions { appRootSelector?: string; appLoadedClass?: string; + displayType?: string; appRootAttributesBlacklist?: string[]; mockAttributesBlacklist?: string[]; } @@ -22,7 +24,8 @@ export function getFlashPreventionPlugin({ appRootSelector, appLoadedClass, appRootAttributesBlacklist, - mockAttributesBlacklist + mockAttributesBlacklist, + displayType }: FlashPreventionPluginOptions = {}) { if (appRootSelector) { AppRootSelector = appRootSelector; @@ -30,6 +33,9 @@ export function getFlashPreventionPlugin({ if (appLoadedClass) { LoadedClass = appLoadedClass; } + if (displayType) { + DisplayType = displayType; + } pushItemsToArray(appRootAttributesBlacklist, AppRootAttrsBlacklist); pushItemsToArray(mockAttributesBlacklist, MockRootAttrsBlacklist); @@ -87,8 +93,8 @@ async function addBitsToHead(html) { `;