diff --git a/packages/async-loader/async.js b/packages/async-loader/async.js index 860908a32..252c7f953 100644 --- a/packages/async-loader/async.js +++ b/packages/async-loader/async.js @@ -1,36 +1,31 @@ import { h, Component } from 'preact'; -export default function(req) { - function Async() { - Component.call(this); - - let b, old; - this.componentWillMount = () => { - b = this.base = this.nextBase || this.__b; // short circuits 1st render - req(m => { - this.setState({ child: m.default || m }); - }); - }; +const PENDING = {}; - this.shouldComponentUpdate = (_, nxt) => { - nxt = nxt.child === void 0; - if (nxt && old === void 0 && b) { - // Node.TEXT_NODE - if (b.nodeType === 3) { - old = b.data; - } else { - old = h(b.nodeName, { - dangerouslySetInnerHTML: { __html: b.innerHTML }, - }); - } - } else { - old = ''; // dump it - } - return !nxt; - }; +function Pending() { + throw PENDING; +} - this.render = (p, s) => (s.child ? h(s.child, p) : old); +export default function async(load) { + let component; + function AsyncComponent() { + Component.call(this); + if (!component) { + (this.componentWillMount = () => { + load(mod => { + component = (mod && mod.default) || mod; + this.componentDidCatch = null; + this.setState({}); + }); + }), + (this.componentDidCatch = err => { + if (err !== PENDING) throw err; + }); + this.shouldComponentUpdate = () => component != null; + } + this.render = props => h(component || Pending, props); } - (Async.prototype = new Component()).constructor = Async; - return Async; + AsyncComponent.preload = load; + (AsyncComponent.prototype = new Component()).constructor = AsyncComponent; + return AsyncComponent; } diff --git a/packages/async-loader/index.js b/packages/async-loader/index.js index d4fde234b..d2010f06f 100644 --- a/packages/async-loader/index.js +++ b/packages/async-loader/index.js @@ -1,3 +1,4 @@ +const path = require('path'); const { getOptions, stringifyRequest } = require('loader-utils'); exports.pitch = function(req) { @@ -16,8 +17,12 @@ exports.pitch = function(req) { name = query.formatName(this.resourcePath); } + // import Async from '${path.relative(process.cwd(), path.resolve(__dirname, 'async-component.js'))}'; return ` - import Async from '@preact/async-loader/async'; + import Async from ${stringifyRequest( + this, + path.resolve(__dirname, 'async.js') + )}; function load(cb) { require.ensure([], function (require) { diff --git a/packages/cli/lib/lib/entry.js b/packages/cli/lib/lib/entry.js index 9ce0d6f08..3a71f2b17 100644 --- a/packages/cli/lib/lib/entry.js +++ b/packages/cli/lib/lib/entry.js @@ -1,6 +1,6 @@ /* global __webpack_public_path__ */ -import { h, render } from 'preact'; +import { h, render, hydrate } from 'preact'; const interopDefault = m => (m && m.default ? m.default : m); @@ -32,7 +32,8 @@ if (process.env.NODE_ENV === 'development') { let app = interopDefault(require('preact-cli-entrypoint')); if (typeof app === 'function') { - let root = document.body.firstElementChild; + let root = + document.getElementById('preact_root') || document.body.firstElementChild; let init = () => { let app = interopDefault(require('preact-cli-entrypoint')); @@ -48,7 +49,11 @@ if (typeof app === 'function') { * to send other data like at some point in time. */ const CLI_DATA = { preRenderData }; - root = render(h(app, { CLI_DATA }), document.body, root); + const doRender = + process.env.NODE_ENV !== 'production' || root.tagName !== 'script' + ? render + : hydrate; + root = doRender(h(app, { CLI_DATA }), document.body, root); }; if (module.hot) module.hot.accept('preact-cli-entrypoint', init);