diff --git a/.eslintrc b/.eslintrc index 1e285ad..05e24cc 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,3 +1,6 @@ { - "extends": "airbnb-base" + "extends": "airbnb-base", + "rules": { + "arrow-body-style": 0 + } } \ No newline at end of file diff --git a/README.md b/README.md index 510b278..692af2e 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,10 @@ module.exports = { new NovaConsumerPlugin({ novas: [ { - entry: 'http://localhost:8080/client.js' + entry: 'http://localhost:8080/client.js', + views: [ + 'ExampleView' + ] } ] }) @@ -31,5 +34,21 @@ module.exports = { ### Live Reload -This plugin create a socket connection for each Nova that is running with `webpack-dev-server` in development mode. Then the page is reload everytime that the Nova code is compiled with webpack. +The plugin creates a socket connection for each Nova that is running with `webpack-dev-server` in development mode. Then the page is reload everytime that the Nova code is compiled with webpack. + +### Lazy Load + +Lazy load is enabled by default when webpack runs in production mode. It generates a script file that loads the Nova `entry` when a view listed in the `views` field is placed in the page using the [Nova Bridge](https://ara-framework.github.io/website/docs/nova-bridge) + +Example using [nova-vue-bridge](https://www.npmjs.com/package/nova-vue-bridge): + +```vue + +``` + +The entry point `http://localhost:8080/client.js` is loaded when Vue.js mounts the previous component. \ No newline at end of file diff --git a/index.js b/index.js index 6345031..c289858 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,5 @@ const url = require('url'); +const qs = require('querystring'); class NovaConsumerPlugin { constructor(opts = {}) { @@ -21,23 +22,38 @@ class NovaConsumerPlugin { } }); }); - } - - compiler.hooks.compilation.tap('NovaConsumerPlugin', (context) => { - context.hooks.htmlWebpackPluginBeforeHtmlProcessing.tapAsync('NovaConsumerPlugin', (data, cb) => { - const { assets } = data; + } else { + compiler.hooks.entryOption.tap('NovaConsumerPlugin', (context, entry) => { const { novas = [] } = this.opts; - novas.forEach((nova) => { - const { entry } = nova; + const viewsMap = novas.reduce((acc, { views = [], entry: novaEntry }) => { + return views.reduce((acc2, view) => { + acc2[view] = novaEntry; // eslint-disable-line no-param-reassign + return acc2; + }, acc); + }, {}); - if (entry) { - assets.js.push(entry); - } + entry['nova-lazy-load'] = `@ara/webpack-nova-consumer/lazy?${qs.encode(viewsMap)}`; // eslint-disable-line no-param-reassign + }); + } + + if (compiler.options.mode === 'development') { + compiler.hooks.compilation.tap('NovaConsumerPlugin', (context) => { + context.hooks.htmlWebpackPluginBeforeHtmlProcessing.tapAsync('NovaConsumerPlugin', (data, cb) => { + const { assets } = data; + const { novas = [] } = this.opts; + + novas.forEach((nova) => { + const { entry } = nova; + + if (entry) { + assets.js.push(entry); + } + }); + cb(); }); - cb(); }); - }); + } } } diff --git a/lazy.js b/lazy.js new file mode 100644 index 0000000..2bb40e9 --- /dev/null +++ b/lazy.js @@ -0,0 +1,32 @@ +/* eslint-disable no-undef */ + +const querystring = require('querystring'); + +const loadScript = (src) => new Promise((resolve) => { + if (document.querySelector(`script[src="${src}"]`)) { + return resolve(); + } + + const el = document.createElement('script'); + + el.type = 'text/javascript'; + el.async = true; + el.src = src; + + document.head.appendChild(el); + return resolve(); +}); + +if (__resourceQuery) { + const viewsMap = querystring.parse(__resourceQuery.slice(1)); + + document.addEventListener('NovaMount', ({ detail }) => { + const { name } = detail; + + const src = viewsMap[name]; + + if (src) { + loadScript(src); + } + }); +}