From 428599cdc7fd83fbd69e2bde810bd9e7925b4f71 Mon Sep 17 00:00:00 2001 From: Morgane Dubus Date: Wed, 5 Dec 2018 13:36:44 +0100 Subject: [PATCH] docs: add website --- .eslintignore | 2 + .github/ISSUE_TEMPLATE/feature.md | 2 +- .prettierignore | 4 +- CONTRIBUTING.md | 2 +- README.md | 305 +- examples/razzle/razzle.config.js | 42 +- examples/razzle/src/About/index.js | 6 +- examples/razzle/src/App.js | 20 +- examples/razzle/src/Contact/index.js | 6 +- examples/razzle/src/Home/Intro.js | 6 +- examples/razzle/src/Home/Logo.js | 8 +- examples/razzle/src/Home/Welcome.js | 6 +- examples/razzle/src/Home/index.js | 16 +- examples/razzle/src/NotFound/index.js | 6 +- examples/razzle/src/client.js | 20 +- examples/razzle/src/index.js | 42 +- examples/razzle/src/server.js | 37 +- .../server-side-rendering/src/server/main.js | 1 + netlify.toml | 11 + packages/webpack-plugin/src/index.js | 2 +- website/.eslintignore | 3 + website/.gitignore | 3 + website/README.md | 30 + website/gatsby-config.js | 10 + website/gatsby-node.js | 13 + website/package.json | 13 + website/src/images/home-logo.png | Bin 0 -> 15692 bytes website/src/images/logo.png | Bin 0 -> 15692 bytes website/src/pages/404.mdx | 7 + .../src/pages/docs/api-loadable-component.mdx | 87 + .../src/pages/docs/api-loadable-server.mdx | 124 + .../docs/api-loadable-webpack-plugin.mdx | 23 + website/src/pages/docs/code-splitting.mdx | 66 + .../src/pages/docs/component-splitting.mdx | 23 + website/src/pages/docs/delay.mdx | 19 + website/src/pages/docs/dynamic-import.mdx | 24 + website/src/pages/docs/error-boundaries.mdx | 26 + website/src/pages/docs/fallback.mdx | 37 + website/src/pages/docs/getting-started.mdx | 41 + website/src/pages/docs/library-splitting.mdx | 54 + .../src/pages/docs/loadable-vs-react-lazy.mdx | 70 + website/src/pages/docs/prefetching.mdx | 21 + .../src/pages/docs/server-side-rendering.mdx | 190 + website/src/pages/docs/suspense.mdx | 29 + website/src/pages/docs/timeout.mdx | 19 + website/src/pages/index.mdx | 48 + website/yarn.lock | 13697 ++++++++++++++++ 47 files changed, 14816 insertions(+), 405 deletions(-) create mode 100644 netlify.toml create mode 100644 website/.eslintignore create mode 100644 website/.gitignore create mode 100644 website/README.md create mode 100644 website/gatsby-config.js create mode 100644 website/gatsby-node.js create mode 100644 website/package.json create mode 100644 website/src/images/home-logo.png create mode 100644 website/src/images/logo.png create mode 100644 website/src/pages/404.mdx create mode 100644 website/src/pages/docs/api-loadable-component.mdx create mode 100644 website/src/pages/docs/api-loadable-server.mdx create mode 100644 website/src/pages/docs/api-loadable-webpack-plugin.mdx create mode 100644 website/src/pages/docs/code-splitting.mdx create mode 100644 website/src/pages/docs/component-splitting.mdx create mode 100644 website/src/pages/docs/delay.mdx create mode 100644 website/src/pages/docs/dynamic-import.mdx create mode 100644 website/src/pages/docs/error-boundaries.mdx create mode 100644 website/src/pages/docs/fallback.mdx create mode 100644 website/src/pages/docs/getting-started.mdx create mode 100644 website/src/pages/docs/library-splitting.mdx create mode 100644 website/src/pages/docs/loadable-vs-react-lazy.mdx create mode 100644 website/src/pages/docs/prefetching.mdx create mode 100644 website/src/pages/docs/server-side-rendering.mdx create mode 100644 website/src/pages/docs/suspense.mdx create mode 100644 website/src/pages/docs/timeout.mdx create mode 100644 website/src/pages/index.mdx create mode 100644 website/yarn.lock diff --git a/.eslintignore b/.eslintignore index e7322c4..d6a1444 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,3 +3,5 @@ node_modules/ dist/ lib/ build/ +/website/.cache/ +/website/public/ \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md index 0100c2e..d216fbe 100644 --- a/.github/ISSUE_TEMPLATE/feature.md +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -17,4 +17,4 @@ Please provide an example for how this feature would be used. ## Pitch -Why does this feature belong in the SVGR ecosystem? +Why does this feature belong in the Loadable Component ecosystem? diff --git a/.prettierignore b/.prettierignore index 267b176..5255f59 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,4 +4,6 @@ node_modules/ __fixtures__/ CHANGELOG.md package.json -lerna.json \ No newline at end of file +lerna.json +/website/.cache/ +/website/public/ \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2398b97..793bae4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ We expect project participants to adhere to our Code of Conduct. Please read [th ## Open Development -All work on SVGR happens directly on [GitHub](/). Both core team members and external contributors send pull requests which go through the same review process. +All work on Loadable Components happens directly on [GitHub](/). Both core team members and external contributors send pull requests which go through the same review process. ### Workflow and Pull Requests diff --git a/README.md b/README.md index e556403..78306bb 100644 --- a/README.md +++ b/README.md @@ -12,32 +12,21 @@ [![DevDependencies](https://img.shields.io/david/dev/smooth-code/loadable-components.svg)](https://david-dm.org/smooth-code/loadable-components?type=dev) [![Small size](https://img.badgesize.io/https://unpkg.com/@loadable/component/dist/loadable.min.js?compression=gzip)](https://unpkg.com/@loadable/component/dist/loadable.min.js) -```sh +```bash npm install @loadable/component ``` -## Introduction +## [Docs](https://www.smooth-code.com/open-source/loadable-components) -Code splitting is supported out of the box by React using [`React.lazy`](https://reactjs.org/docs/code-splitting.html#reactlazy). So what is the goal of this library? +**See the documentation at [smooth-code.com/open-source/loadable-components](https://www.smooth-code.com/open-source/loadable-components)** for more information about using `loadable components`! -`@loadable/component` pushes the limit of Code splitting, it offers several features: +Quicklinks to some of the most-visited pages: -- πŸ“š Library splitting -- ⚑️ Prefetching -- πŸ’« Server Side Rendering -- πŸŽ› Full dynamic import `` import(`./${value}`) `` +- [**Getting started**](https://www.smooth-code.com/open-source/loadable-components/docs/getting-started/) +- [Comparison with React.lazy](https://www.smooth-code.com/open-source/loadable-components/docs/loadable-vs-react-lazy/) +- [Server Side Rendering](https://www.smooth-code.com/open-source/loadable-components/docs/server-side-rendering/) -## Comparison with React.lazy & react-loadable - -| Library | Suspense | SSR | Library splitting | `` import(`./${value}`) `` | -| --------------------- | -------- | --- | ----------------- | -------------------------- | -| `React.lazy` | βœ… | ❌ | ❌ | ❌ | -| `react-loadable` | ❌ | πŸ”Ά | ❌ | ❌ | -| `@loadable/component` | βœ… | βœ… | βœ… | βœ… | - -## Getting started - -`loadable` lets you render a dynamic import as a regular component. +## Example ```js import loadable from '@loadable/component' @@ -53,280 +42,8 @@ function MyComponent() { } ``` -### Loading library +## Licence -`loadable.lib` lets you defer the loading of a library. It takes a render props called when the library is loaded. +Licensed under the MIT License, Copyright Β© 2017-present Smooth Code. -```js -import loadable from '@loadable/component' - -const Moment = loadable.lib(() => import('moment')) - -function FromNow({ date }) { - return ( -
- - {({ default: moment }) => moment(date).fromNow()} - -
- ) -} -``` - -You can also use a `ref`, populated when the library is loaded. - -```js -import loadable from '@loadable/component' - -const Moment = loadable.lib(() => import('moment')) - -class MyComponent { - moment = React.createRef() - - handleClick = () => { - if (this.moment.current) { - return alert(this.moment.current.default.format('HH:mm')) - } - } - - render() { - return ( -
- - -
- ) - } -} -``` - -> You can also pass a function to `ref`, called when the library is loaded. - -### Full dynamic import - -Webpack accepts [full dynamic imports](https://webpack.js.org/api/module-methods/#import-), you can use them to create a reusable Loadable Component. - -```js -import loadable from '@loadable/component' - -const AsyncPage = loadable(props => import(`./${props.page}`)) - -function MyComponent() { - return ( -
- - -
- ) -} -``` - -### Suspense - -`@loadable/component` exposes a `lazy` method that acts similarly as `React.lazy` one. - -```js -import { lazy } from '@loadable/component' - -const OtherComponent = lazy(() => import('./OtherComponent')) - -function MyComponent() { - return ( -
- Loading...
}> - - - - ) -} -``` - -> Use `lazy.lib` for libraries. - -> ⚠️ Suspense is not yet available for server-side rendering. - -### Fallback without Suspense - -You can specify a `fallback` in `loadable` options. - -```js -const OtherComponent = loadable(() => import('./OtherComponent'), { - fallback:
Loading...
, -}) - -function MyComponent() { - return ( -
- -
- ) -} -``` - -You can also specify a `fallback` in props: - -```js -const OtherComponent = loadable(() => import('./OtherComponent')) - -function MyComponent() { - return ( -
- Loading...
} /> - - ) -} -``` - -### Error boundaries - -If the other module fails to load (for example, due to network failure), it will trigger an error. You can handle these errors to show a nice user experience and manage recovery with [Error Boundaries](https://reactjs.org/docs/error-boundaries.html). Once you’ve created your Error Boundary, you can use it anywhere above your lazy components to display an error state when there’s a network error. - -```js -import MyErrorBoundary from '/MyErrorBoundary' -const OtherComponent = loadable(() => import('./OtherComponent')) -const AnotherComponent = loadable(() => import('./AnotherComponent')) - -const MyComponent = () => ( -
- -
- - -
-
-
-) -``` - -### Delay - -To avoid flashing a loader if the loading is very fast, you could implement a minimum delay. There is no built-in API in `@loadable/component` but you could do it using [`p-min-delay`](https://github.com/sindresorhus/p-min-delay). - -```js -import loadable from '@loadable/component' -import pMinDelay from 'p-min-delay' - -// Wait a minimum of 200ms before loading home. -export const OtherComponent = loadable(() => - pMinDelay(import('./OtherComponent'), 200), -) -``` - -### Timeout - -Infinite loading is not good for user experience, to avoid it implementing a timeout is a good workaround. You can do it using a third party module like [`promise-timeout`](https://github.com/building5/promise-timeout): - -```js -import loadable from '@loadable/component' -import { timeout } from 'promise-timeout' - -// Wait a maximum of 2s before sending an error. -export const OtherComponent = loadable(() => - timeout(import('./OtherComponent'), 2000), -) -``` - -### Prefetching - -Loadable Components is fully compatible with [webpack hints `webpackPrefetch` and `webpackPreload`](https://webpack.js.org/guides/code-splitting/#prefetching-preloading-modules). - -Most of the time, you want to "prefetch" a component, it means it will be loaded when the browser is idle. You can do it by adding `/* webpackPrefetch: true */` inside your import statement. - -```js -import loadable from '@loadable/component' - -const OtherComponent = loadable(() => - import(/* webpackPrefetch: true */ './OtherComponent'), -) -``` - -> You can extract prefetched resources server-side to add `` in your head. - -## [Server side rendering](https://github.com/smooth-code/loadable-components/tree/master/packages/server/README.md) - -πŸ‘‰ [See `@loadable/server` documentation](https://github.com/smooth-code/loadable-components/tree/master/packages/server/README.md). - - -## API - -### loadable - -Create a loadable component. - -| Arguments | Description | -| ------------------ | ---------------------------------------- | -| `loadFn` | The function call to load the component. | -| `options` | Optional options. | -| `options.fallback` | Fallback displayed during the loading. | - -```js -import loadable from '@loadable/component' - -const OtherComponent = loadable(() => import('./OtherComponent')) -``` - -### lazy - -Create a loadable component "Suspense" ready. - -| Arguments | Description | -| --------- | ---------------------------------------- | -| `loadFn` | The function call to load the component. | - -```js -import { lazy } from '@loadable/component' - -const OtherComponent = lazy(() => import('./OtherComponent')) -``` - -### LoadableComponent - -A component created using `loadable` or `lazy`. - -| Props | Description | -| ---------- | ------------------------------------------------- | -| `fallback` | Fallback displayed during the loading. | -| `...` | Props are forwarded as first argument of `loadFn` | - -### loadable.lib - -Create a loadable library. - -| Arguments | Description | -| ------------------ | ---------------------------------------- | -| `loadFn` | The function call to load the component. | -| `options` | Optional options. | -| `options.fallback` | Fallback displayed during the loading. | - -```js -import loadable from '@loadable/component' - -const Moment = loadable.lib(() => import('moment')) -``` - -### lazy.lib - -Create a loadable library "Suspense" ready. - -| Arguments | Description | -| --------- | ---------------------------------------- | -| `loadFn` | The function call to load the component. | - -```js -import { lazy } from '@loadable/component' - -const Moment = lazy.lib(() => import('moment')) -``` - -### LoadableLibrary - -A component created using `loadable.lib` or `lazy.lib`. - -| Props | Description | -| ---------- | ---------------------------------------------------- | -| `children` | Function called when the library is loaded. | -| `ref` | Accepts a ref, populated when the library is loaded. | -| `fallback` | Fallback displayed during the loading. | -| `...` | Props are forwarded as first argument of `loadFn` | - -## MIT +See [LICENSE](./LICENSE) for more information. diff --git a/examples/razzle/razzle.config.js b/examples/razzle/razzle.config.js index 63f5f24..d90b123 100644 --- a/examples/razzle/razzle.config.js +++ b/examples/razzle/razzle.config.js @@ -1,27 +1,27 @@ -const path = require('path'); -const LoadableWebpackPlugin = require('@loadable/webpack-plugin'); -const LoadableBabelPlugin = require('@loadable/babel-plugin'); -const babelPresetRazzle = require('razzle/babel'); +const path = require('path') +const LoadableWebpackPlugin = require('@loadable/webpack-plugin') +const LoadableBabelPlugin = require('@loadable/babel-plugin') +const babelPresetRazzle = require('razzle/babel') module.exports = { - modify: (config, { target }) => { - const appConfig = Object.assign({}, config); + modify: (config, { target }) => { + const appConfig = Object.assign({}, config) - if (target === 'web') { - const filename = path.resolve(__dirname, 'build/loadable-stats.json'); + if (target === 'web') { + const filename = path.resolve(__dirname, 'build/loadable-stats.json') - appConfig.plugins = [ - ...appConfig.plugins, - new LoadableWebpackPlugin({ writeToDisk: true, filename }) - ]; - } + appConfig.plugins = [ + ...appConfig.plugins, + new LoadableWebpackPlugin({ writeToDisk: true, filename }), + ] + } - return appConfig; - }, + return appConfig + }, - modifyBabelOptions: () => ({ - babelrc: false, - presets: [babelPresetRazzle], - plugins: [LoadableBabelPlugin] - }) -}; + modifyBabelOptions: () => ({ + babelrc: false, + presets: [babelPresetRazzle], + plugins: [LoadableBabelPlugin], + }), +} diff --git a/examples/razzle/src/About/index.js b/examples/razzle/src/About/index.js index 8ea2507..9a6c8bf 100644 --- a/examples/razzle/src/About/index.js +++ b/examples/razzle/src/About/index.js @@ -1,5 +1,5 @@ -import React from 'react'; +import React from 'react' -const About = () => (
About page
); +const About = () =>
About page
-export default About; \ No newline at end of file +export default About diff --git a/examples/razzle/src/App.js b/examples/razzle/src/App.js index e7bcfbb..bf1055d 100644 --- a/examples/razzle/src/App.js +++ b/examples/razzle/src/App.js @@ -1,12 +1,12 @@ -import React from 'react'; -import { Router, Link } from '@reach/router'; -import loadable from '@loadable/component'; -import './App.css'; +import React from 'react' +import { Router, Link } from '@reach/router' +import loadable from '@loadable/component' +import './App.css' -const NotFound = loadable(() => import('./NotFound')); -const Home = loadable(() => import('./Home')); -const About = loadable(() => import('./About')); -const Contact = loadable(() => import('./Contact')); +const NotFound = loadable(() => import('./NotFound')) +const Home = loadable(() => import('./Home')) +const About = loadable(() => import('./About')) +const Contact = loadable(() => import('./Contact')) const App = () => ( @@ -20,6 +20,6 @@ const App = () => ( loading...} /> -); +) -export default App; +export default App diff --git a/examples/razzle/src/Contact/index.js b/examples/razzle/src/Contact/index.js index f974cc9..8941afb 100644 --- a/examples/razzle/src/Contact/index.js +++ b/examples/razzle/src/Contact/index.js @@ -1,5 +1,5 @@ -import React from 'react'; +import React from 'react' -const Contact = () => (
Contact page
); +const Contact = () =>
Contact page
-export default Contact; \ No newline at end of file +export default Contact diff --git a/examples/razzle/src/Home/Intro.js b/examples/razzle/src/Home/Intro.js index 47705b0..0ddfba1 100644 --- a/examples/razzle/src/Home/Intro.js +++ b/examples/razzle/src/Home/Intro.js @@ -1,11 +1,11 @@ /* eslint-disable react/jsx-one-expression-per-line */ -import React from 'react'; +import React from 'react' const Intro = () => (

To get started, edit src/App.js or src/Home.js and save to reload.

-); +) -export default Intro; +export default Intro diff --git a/examples/razzle/src/Home/Logo.js b/examples/razzle/src/Home/Logo.js index 84d99bf..96de7c7 100644 --- a/examples/razzle/src/Home/Logo.js +++ b/examples/razzle/src/Home/Logo.js @@ -1,6 +1,6 @@ -import React from 'react'; -import logo from './react.svg'; +import React from 'react' +import logo from './react.svg' -const Logo = () => logo; +const Logo = () => logo -export default Logo; +export default Logo diff --git a/examples/razzle/src/Home/Welcome.js b/examples/razzle/src/Home/Welcome.js index 195b0fd..958bc0c 100644 --- a/examples/razzle/src/Home/Welcome.js +++ b/examples/razzle/src/Home/Welcome.js @@ -1,5 +1,5 @@ -import React from 'react'; +import React from 'react' -const Welcome = () =>

Welcome to Razzle

; +const Welcome = () =>

Welcome to Razzle

-export default Welcome; +export default Welcome diff --git a/examples/razzle/src/Home/index.js b/examples/razzle/src/Home/index.js index aa43bcc..9a156ac 100644 --- a/examples/razzle/src/Home/index.js +++ b/examples/razzle/src/Home/index.js @@ -1,10 +1,10 @@ -import React from 'react'; -import loadable from '@loadable/component'; -import './Home.css'; +import React from 'react' +import loadable from '@loadable/component' +import './Home.css' -const Intro = loadable(() => import('./Intro')); -const Welcome = loadable(() => import('./Welcome')); -const Logo = loadable(() => import('./Logo')); +const Intro = loadable(() => import('./Intro')) +const Welcome = loadable(() => import('./Welcome')) +const Logo = loadable(() => import('./Logo')) const Home = () => (
@@ -25,6 +25,6 @@ const Home = () => (
-); +) -export default Home; +export default Home diff --git a/examples/razzle/src/NotFound/index.js b/examples/razzle/src/NotFound/index.js index bd9eebd..7ff6641 100644 --- a/examples/razzle/src/NotFound/index.js +++ b/examples/razzle/src/NotFound/index.js @@ -1,5 +1,5 @@ -import React from 'react'; +import React from 'react' -const NotFound = () => (
Page could not be found
); +const NotFound = () =>
Page could not be found
-export default NotFound; \ No newline at end of file +export default NotFound diff --git a/examples/razzle/src/client.js b/examples/razzle/src/client.js index 5a31c59..ec8b404 100644 --- a/examples/razzle/src/client.js +++ b/examples/razzle/src/client.js @@ -1,18 +1,14 @@ -import React from 'react'; -import { hydrate } from 'react-dom'; -import { loadableReady } from '@loadable/component'; -import App from './App'; +import React from 'react' +import { hydrate } from 'react-dom' +import { loadableReady } from '@loadable/component' +import App from './App' -const root = document.getElementById('root'); +const root = document.getElementById('root') loadableReady(() => { - hydrate( - , - root - ); -}); + hydrate(, root) +}) if (module.hot) { - module.hot.accept(); + module.hot.accept() } - diff --git a/examples/razzle/src/index.js b/examples/razzle/src/index.js index 59b2595..adb2163 100644 --- a/examples/razzle/src/index.js +++ b/examples/razzle/src/index.js @@ -1,34 +1,34 @@ /* eslint-disable no-console, global-require */ -import http from 'http'; +import http from 'http' -let app = require('./server').default; +let app = require('./server').default -const server = http.createServer(app); +const server = http.createServer(app) -let currentApp = app; +let currentApp = app server.listen(process.env.PORT || 3000, error => { - if (error) { - console.log(error); - } + if (error) { + console.log(error) + } - console.log('πŸš€ started'); -}); + console.log('πŸš€ started') +}) if (module.hot) { - console.log('βœ… Server-side HMR Enabled!'); + console.log('βœ… Server-side HMR Enabled!') - module.hot.accept('./server', () => { - console.log('πŸ” HMR Reloading `./server`...'); + module.hot.accept('./server', () => { + console.log('πŸ” HMR Reloading `./server`...') - try { - app = require('./server').default; - server.removeListener('request', currentApp); - server.on('request', app); - currentApp = app; - } catch (error) { - console.error(error); - } - }); + try { + app = require('./server').default + server.removeListener('request', currentApp) + server.on('request', app) + currentApp = app + } catch (error) { + console.error(error) + } + }) } diff --git a/examples/razzle/src/server.js b/examples/razzle/src/server.js index 4636303..6e8cda4 100644 --- a/examples/razzle/src/server.js +++ b/examples/razzle/src/server.js @@ -1,28 +1,32 @@ -import path from 'path'; -import React from 'react'; -import express from 'express'; -import { html as htmlTemplate, oneLineTrim } from 'common-tags'; -import { renderToString } from 'react-dom/server'; -import { ServerLocation } from '@reach/router'; -import { ChunkExtractor, ChunkExtractorManager } from '@loadable/server'; -import App from './App'; +import path from 'path' +import React from 'react' +import express from 'express' +import { html as htmlTemplate, oneLineTrim } from 'common-tags' +import { renderToString } from 'react-dom/server' +import { ServerLocation } from '@reach/router' +import { ChunkExtractor, ChunkExtractorManager } from '@loadable/server' +import App from './App' -const server = express(); +const server = express() server .disable('x-powered-by') .use(express.static(process.env.RAZZLE_PUBLIC_DIR)) .get('/*', (req, res) => { - const extractor = new ChunkExtractor({ statsFile: path.resolve('build/loadable-stats.json'), entrypoints: ['client'] }); + const extractor = new ChunkExtractor({ + statsFile: path.resolve('build/loadable-stats.json'), + entrypoints: ['client'], + }) const html = renderToString( - - ); + , + ) - res.status(200).send(oneLineTrim(htmlTemplate` + res.status(200).send( + oneLineTrim(htmlTemplate` @@ -38,7 +42,8 @@ server ${extractor.getScriptTags()} - `)); - }); + `), + ) + }) -export default server; +export default server diff --git a/examples/server-side-rendering/src/server/main.js b/examples/server-side-rendering/src/server/main.js index 42522a1..716eea3 100644 --- a/examples/server-side-rendering/src/server/main.js +++ b/examples/server-side-rendering/src/server/main.js @@ -65,4 +65,5 @@ ${webExtractor.getStyleTags()} }), ) +// eslint-disable-next-line no-console app.listen(9000, () => console.log('Server started http://localhost:9000')) diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000..54490fb --- /dev/null +++ b/netlify.toml @@ -0,0 +1,11 @@ +# Global settings applied to the whole site. +# +# β€œpublish” is the directory to publish (relative to root of your repo), +# β€œcommand” is your build command, +# β€œbase” is directory to change to before starting build. if you set base: +# that is where we will look for package.json/.nvmrc/etc not repo root! + +[build] + base = "website" + publish = "website/public" + command = "yarn build:pp" \ No newline at end of file diff --git a/packages/webpack-plugin/src/index.js b/packages/webpack-plugin/src/index.js index 03640ef..0d302d2 100644 --- a/packages/webpack-plugin/src/index.js +++ b/packages/webpack-plugin/src/index.js @@ -5,7 +5,7 @@ class LoadablePlugin { constructor({ filename = 'loadable-stats.json', writeToDisk = false } = {}) { this.opts = { filename, writeToDisk } - // The Webpack compiler instance + // The Webpack compiler instance this.compiler = null } diff --git a/website/.eslintignore b/website/.eslintignore new file mode 100644 index 0000000..d24a37d --- /dev/null +++ b/website/.eslintignore @@ -0,0 +1,3 @@ +.cache/ +node_modules/ +/public/ \ No newline at end of file diff --git a/website/.gitignore b/website/.gitignore new file mode 100644 index 0000000..d24a37d --- /dev/null +++ b/website/.gitignore @@ -0,0 +1,3 @@ +.cache/ +node_modules/ +/public/ \ No newline at end of file diff --git a/website/README.md b/website/README.md new file mode 100644 index 0000000..5dd6a79 --- /dev/null +++ b/website/README.md @@ -0,0 +1,30 @@ +# Loadable Components website + +[Documentation site](https://www.smooth-code.com/open-source/loadable-components/) for [loadable components](https://github.com/smooth-code/loadable-components). This website is running on [gatsbyjs](gatsbyjs.org). + +## Getting Started + +To install and run the docs site locally: + +```bash +yarn +yarn dev +``` + +Then, open your favorite browser to [localhost:8000](http://localhost:8000/). GraphiQL runs at [localhost:8000/\_\_\_graphql](http://localhost:8000/___graphql). + +## Contributing + +Build the site to test locally. + +```bash +yarn build +``` + +Serve the build. + +```bash +yarn serve +``` + +Then, open your favorite browser to [localhost:9000](http://localhost:9000/) to verify everything looks correct. diff --git a/website/gatsby-config.js b/website/gatsby-config.js new file mode 100644 index 0000000..33d2121 --- /dev/null +++ b/website/gatsby-config.js @@ -0,0 +1,10 @@ +const { getGatsbyConfig } = require('smooth-doc/config') + +module.exports = getGatsbyConfig({ + root: __dirname, + name: 'Loadable Components', + slug: 'loadable-components', + github: 'https://github.com/smooth-code/loadable-components', + menu: ['Introduction', 'Guides', 'API'], + nav: [{ title: 'Docs', url: '/docs/' }], +}) diff --git a/website/gatsby-node.js b/website/gatsby-node.js new file mode 100644 index 0000000..4dd63c3 --- /dev/null +++ b/website/gatsby-node.js @@ -0,0 +1,13 @@ +const { getGatsbyNode } = require('smooth-doc/node') + +module.exports = getGatsbyNode({ + root: __dirname, +}) + +module.exports.createPages = ({ actions }) => { + actions.createRedirect({ + fromPath: `/docs/`, + toPath: `/docs/getting-started/`, + redirectInBrowser: true, + }) +} diff --git a/website/package.json b/website/package.json new file mode 100644 index 0000000..257ac01 --- /dev/null +++ b/website/package.json @@ -0,0 +1,13 @@ +{ + "private": true, + "scripts": { + "build": "gatsby build", + "build:pp": "gatsby build --prefix-paths", + "dev": "gatsby develop", + "serve": "gatsby serve" + }, + "dependencies": { + "gatsby": "^2.0.63", + "smooth-doc": "^0.0.1-alpha.5" + } +} diff --git a/website/src/images/home-logo.png b/website/src/images/home-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..398335e0d046c07826c754b92a8d0626e1f60477 GIT binary patch literal 15692 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 *si~8{sPK#a{>kH88iDo(>o#6 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 literal 0 HcmV?d00001 diff --git a/website/src/images/logo.png b/website/src/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..398335e0d046c07826c754b92a8d0626e1f60477 GIT binary patch literal 15692 zcmbWd1yCJP(A*xVr|wxVw9BCn5O7-5r9vTwH>?yZgn1yIZ(8Tz=mDs&=>b zudVuOr)v82>1jFh%+z#OpNUXWl14)&K!$;VL6en{P=kSih5YCI1ph91`NY}+0|R%j zqM#x9KIP%z;o{=r_#a2t&f5FP$;l}xF2={p`(N_^o&J~Ff9d=eeOG>GX0|uq>AU9K z{Oo_p-}$WypY6h5D{%&MgKht%c9SgpKdtUT3Qc7dki>5dUOtd?&YEBL^#w)G1%v}$ zzFNDmeD za}m>BI`iAQ|4WTN*xnIZs`6T|nwy+*diQvnO!1g6^4wtC($VwO>s>)cnw^lG#K`mv z;v3b}D=;v6Dp$;j`~6!(XWG){<&Va+u=rb-by(%Hv)=cYHmTQemX~~~m><8MMw52c zHT*KV=an=Xn3zmdHDAjFpGv4-+uf=qlz-T`)(h~r$;$s}9ZLV549dtocX3-{WK0eX z^{}+qJUIEQYw+CW6by8pm|u1b%-h^QF3QeHu9|r3a|3H=R5$gWn3;pJa-g%JgTrGD ze+p;+ZZ>ufzJUXlw|4ucR!*(0-=TZk7APB7ec2Q!AKCh+Y2amL0o@b%GqHdF-T2Yi z;#gYsag`71;`!>}@_M3I*fF~&rdT|3@?v9uuB83u{cxs+9ew$iQ($h@uczs(6gXzRRIk-r6m1_OZ*MV0J;w=Wh>} z(9Ac!v*VK}FYl)1OX#WB>yg5YfYi$Z%iB@>+m04=Q}$3&>McAvv%K}n$P7Bh)3J4v zTibUH06Y>?rdql*;?HzAPDeDr_(3)?qCPr^(MbNa&Ge*Xh8Sq$l(G{3O1v}~0J@K)C_dVCig5DD$!-CX_)d47ExmWgdWd|S|(8y$~|OPlH+NDdDE z`|l|(t)Myw^fvarX=PK*!yH@a{nd{Hswt_%pa|Tz ze$2H0h)3d~UP-gHeAp*3t8eiS?VK66NP!a*8J{9{lrkwOT#A*OQ_DaWs`&D1cj*pz zeE~yfQlKvnSBD!R&@ShPzh=<-QWFD?S3hWHYorgfB`0ls@A3Zrei zah!R80@_F7J*fmD`0w>}Xt5+)QMVV4q8m8f%htcbI?OVc&f+~(tjvFYKI*8e?#OdB z7$%lus%nZ%Q9uo0ReYfYDsBXg%u1Q2s)inYGuD~nrskIR}?nZ0xr&q*mr&Tl#{l^FR zlLe0X_6$Vd6u$Um?!A;j5~UIWWf1!PL5=qMJZYCV?Glv_MbH^3m(@L31Aq8>ov8H9 zxCX_j2SuKCN@e)Z%J=~;mF|xu?7{>JLsT32jY7`i}t6PW2kVAg(h58G84n_*Mx{uUp)o1vOB+iY16iQ@Fcgo1FJ#LlPrS@ys> zC4Aljw8@(`@+0N7A)<#x=pU9ARw8G`a+6!ssV%Oc^r*tOWVozSC)PO43Jk z7xHk!EFaVy`@GF(eu8`n3%d}CCaH$6XTybq;i~xxkG)#@D8qZaSA;dmMCYBnDJ+h2 zr0_rdAeq;e#aW*TzVM#?#5H!_YWHmijQupjXo!{HtKpsgnc%1x%CxvHq*6j15%)0_ zR+f>gtX-WmaD)^QsK)CV@ZyHT4S#}ZnAZ;rUPNpl7;-+8pybetTAKThCky~qb_y?G zCoatVz^XLS(&o|B--_xt>W`m%RGvwcq6h~e)0A<4{79EM5l&QNU$k)^dJWMsp?!R_ zBIRN)UeWZMF2O>ajO=2(pX0)M^vO@Z7sqE1^-F5+Y4B9gJ~4{sQ&#YPoSjA$1T~<|c91$0L@CjO0ZG?bYHIwyM2QEY>RJ*-}PhAXa+%iyG zfFUeQnxOk~u|Qi!8p%-fgyId5H;K^>C4FmwS>n(Aky>hN8QoE?GLg&?D%04fWc_D^ zyiM+}4#$YEnv*k=tWlU!dz6J`j5Ln-jI!oIPA;SzHu{4W9$!5LGD&zVcb4`2eO2C) z$JqjW2hDqKg+;=WP&B+m+oX@r;kh`+^NO(H!+T}|r!bFvU5+N3IgGGs2gKHcmYrQi zcnVdQFag>e5OgCs5%qgCKa-KXrLc-)J65PJdc*Wi*mYG;#NapY1?DLz- z(9Md1!Ca_>E1o(O@Ol%DNz8gBOO4Ol&qGqCv`t2ME)p?jZ|Z};r3|_wvRKK;JyON} zs~(SLzrz4w7x;ZtVSn5wQPHsLQUjD21B-d%<1g1y1d(Hk&c_OEcy7+0^A$Svmu~J| zzqY+*jk?QsuRL254Q0@^LKY{VOE~x1QL{(f!i7F0pi=TgRf?h!FA20UvtyBlf;Uf( z1%LFfFs3r5udlOiZnChj1U`MY*uD+&o4T7q8h$E?><`aT9M)^n$B~N_07{nU&iV_5 z?bTcrVDQs{VpWU5J(cW@cVxez85zZnhU>X?N{?S=X!kbh{k8 z-gxyi8gyEzIQh11oawMwdPyoUs&sPtXUL+;!7Y-KR(pgEneEhs5h<~!+GHRc>mfYufy^IF^^`+nL zcqMBxbZtd@Akz{)!ZnJ;(^cCP{^{z%s34dpes`PYoeoAg@-9SPFW;D*Tjd;{-Fu`8 zhO!Hlm+e1YJ#-Gojqe9ZP}II3Iu=TKK~GO5q{1xjYtv!R-!p##fBAP^e#^I-yNS_f z7ZVvP6DoZ=4)}_}0wXA!hmoaKXL5!dkVB$Dd<%Kp2-8KMwvlxqJ$pLMnzBhecgy7J!@U)yi-Fpz4(sHko%!RuGO6@F;X3oBm5 zJyEjGuVF5e9xrZUkh)uxJcZ1YxaNtKMwi6CWGH6B!vU<6L9bUoWPIk!A3p%qS0Ux~V^Y0dHHMi% z=FeaD^8J~_{JZkou*;i{>flK0jSkK(!K}HC)>GQ<+vw`vT3z!oiWy}-eJ>Ln?0Tl} z8pr~pqp!4sGVmAdyGnaa+4_0>DZC=BKKwc*4ioqLz+}%>K(U*epuDoOcH^naz^+Ex zOu8M98Z+;|PddSEeh$V4!(X@WnkrHdQ!1WSk%=%)@aIU)w~ba1KOlaK>>hcl1{HW(MudbCUy@HG45zciE&PNu2ywLNPH$>^b%g5dtZ$I_144Zf3=#R z5G6JcfD?Q#Jx^0JB|x^((|53KvgaOFlqg>Sf;SIjQ3YK~4!=~c+&zSf>yFe3o41{8 zaO<4lPP+R;JTH4W*#E%;&|Fk7AX7$=Fa@r&qKU@f$EkYJZ6&;5Im9E`KS6#KI)uor=mHtIF|M&qw zl^tEA?;Od;F$ZteBo?Yvwi%)dgM4Rsf;zSWD=zY3PiFL)Z|^UH$nZt^OX{^3SThMI zQZoOeMttC7nwNq=4!pFODaXfW5Ob*Tw=fBEPdJ0P$SHAHvl?%|1QG2Jcl~F>qnRl8 zZIWZrb4^ofX=0OrXiWjpWS9eyDR${R8hZ%o<*iMgmF+q%;)(0o)>NbrZR~@J+IZPK z%C)ZnvN_4oD%LYoTZ*&0Pm*{JMSHa(pV^qk?RAS%)fLD&6#ILj!wELB8GE>nxGm)f zIXa&S`mfRMG$cA2-KspH&nMjPK7Wp<=#Ygi)5S$iqGuFeF{tQjoxlhtXuIN7Y^Gy5 zel!bVpWE}OxO_wPRHa?dGAF;rk%MuKOj)orMV`bg8Q~cYAj~^dzWTOiJKD!c?_zA# z>P(TF!y8Va9MkTwIPDkS;=lD5uFY^IV=0-2nx=_EX9gak)O7(}hN>T-F=#vl-QS}b zAN~q}<%I?RP3{TxU|@$1ls_uF8lyQzO#b`9I0@xGb9Ka>;T#JPu>Oux9awy{;VDA8 z^jn)W74$8q*H=*v3&7_V>A8^bB?{+}6{O8r>&=(Pk4bsKo$%06X~k@!YdeVdC5&jI zOvEQ`;(}1<203jtdMALmj(k}AOo{GG1o23J#G{Jnf@t+zqlVWt{V_;cQ5L7|t7K=z z0NT;R=$B^93UG^GqSA*aeR;AF13D6ul81Nsepw?jnC8HZ@<*@3(ry{Kx(H2#fzk z7J=VP-AvR69ENtYPa(yJIAyW0{;i=^65I3_o?2-sMTF zBjX-ZnS<|$s@v>wUGYezNKNt$<;Wsqp|4**0G%D}%ewJC!ITp^21YJ7GeJe2Q)`DL zCp)^L6pnIM+mI){Hb>22N1SsiYBqrVktvB7hlKc((Mk{b?A+1mxiWtK@9VOOgeFg) zip363w=d`_>hD=@W-P{dEd+gmMSEx$q|KyD6zB8>aCk&-!;;E~gWTHD`lo7AAc=ek zG_p|=NO?izUQe!#?fmxgh^LC#JN)T}Wp>hbsBZ5z5?2D*<0e$V-`R`hDaAX(?PEYr zdV}i+uRq_|Ip#Q}PK1D^S_O3^Xq}=T1cs4-zNR&JnZ#MCscyrbZ{W}xHbn&-9864a z{&p1C$zZLpSmMVA-Z0B8PX!7zpolViemUba3JfuWVO{>P*l=`;a-$7$1Kw$Fvj8hA z+|1^Hilk~KIj%$?W8tn2$)wljh+7MTW5P#(M1?21(aF9FxgQn{Z(MNf*Ojx?5MzqWN>fG;A7P z_UOcbq>6NM#(#M8 z?G>dx13u3%k8`e4WQdL_t;GCO3xRDyYQ!g$+s#7S(cHrVG`u7;9@Eyqj?dqBz8(s9 z`^CFD*WNyCPZP4NcfYYI*8ji;3BB5@V9<{|^2Y1zh*t^0J#rMVUsJii!4dbOpYQ<; zq(aq*cTOqeuO7O$Pv;q@cBLoa0heDZwK&X4K_M1Pt-0EUbzPk#w^t9Tc#91U@T!MA zqB7TW`+eO;JvhVG`0*opOer!?_o;HvO6m2+8YOPZj;mbsNF#i(Ppr#xbIwlR@?zy& zF3~}-U23^dtOy+qhZl=XoJ02BYyT-5sS33V`!neHq2Gmz<9ZI-edQ9~VWloMW_%MP zt0hKSqA|uCD$Wa<4-FfU#bw*8Pa*b`QaTm@?nG|BV3@8H4RWzwZ#6v;5wW*C5I3S- zsnhs#L3!DBO_W59VYSJ&;$jXYE+ewpUoo=q7X$~n?80cozAjie7`l;Gi z{_w8N-F!W#fZq_+=WED)?+A$taQ(!E=~jQcO#VAwt*AXO?1VVdmE(E@z~yA#=bw3? za%xaRPLlgjC{g}|?!NrLq;{n+IE*U|v+jyYPYM49@;v_Bt#aP>hV#b4 z*mq|H0OvDIczUxNXT;*+{cH#b_Z=mDrY^X@GuAV)97h8;>~Ju)F)GzB4B>u#g!Syxn@OG< z(FotQRK?x{E-VZt;5A4}d%d|L75dRxHNtrWpZrNAP%=&{O`yt`khZpXB+dU zNrB@Bu9F3S`CN>bTCKDndwMk7e|b_FyLl4f&SB6VBgLX;3kiVJ{fgM7rKLd_l7T2F z_C}qazTEAVHXJV{2qy@s-MIXWZmMUxLsP$>;a#;0{>07gU}F(|XnSFex6cM^J}p$F z8d{(kFhXYcp&`C1e*6r1QBCMSDmZhs7(-HjI=c;vrv?zG3yKT2Ps~p0Cbw4}2+g{$ z_TP_2si0?@(jLgaO0eM_#IoD|w25VX1+yGkvSo!rBXoqqc@3h>xf) zVh#l(I~Pj+p2hR^c~Rfo_zLF;eNHt={~XU?V(#gc98_HN%cqA<@jp#Cb^FIUEPms8 zX6$m;yX<%RMS6NF9ON10q^@z{K=XS=vg~xGIuGQ0K%xgF*e3rGm?)lV)v%h&oq&8C z#2+iKuYOc;8u)l>-$x@aEKgn;^rUM~I$&dgxu(hBZ_@f_)%XfW1e}%u+nM-A?SI~*wpLy=lkG|5B%h535t8wGa zy6zQ~GPu8IoQX5O7->BI++@h^wEvO#YfO!c+#GFpT_{vK^brA^K?k(muXMFbL9y+O zlPBE1;hE4}Bznly40HDUy!`bY%@{c$s!dPHKn^&Aj9DtZ5=$On3|}5)CDIY8RgNWJ zHrD*K=ZD+emfl0hw0h1I;fty_9tb7&4N&mt) ztgnUi+RU3=>C3qEGdA~+ z*)y}ptM&*-!QM(aYxUp^z+W(x_YBVx zr6wa7DYx#1W{7T(3x|@ub~1(RyhPY$dEvD==i5TxL|5u1nk`!Z%~%P`x7l#-?Rkac zrhPFG32SdhIlc(HD+NnCFFW)K0Zd{-%`dWAm-Vp6t2Lir0_J8VS@1h%l%v}o!%B!) z5weC+^*<4%O^IMEkMc7^d|dc|qY+<^E#QGa5}&7fBhX02FUG$|t|qVI-%#MGaO0r)$t6JLeK8H6w6)vaFf0jNC$Z}8mMR*OhEN?a^%fy8^!LR z-NI1dSj>ZO zUnwzTH1OXrwA_oFbrd1p8g~qlIdXyPQYAF^MrcU<} zMJ@0PK%t_q0@b$>#6di@^ESLdkHjY91hW|=XQD@0JY?V_rN%){oQClBK@|_gVrnhS z2Uk{`cXHK};c;+=4dE#7{ayxit7e4)r8S}zoC1#7@~~Z(>82ZCKfwaFgCvERDY2eZ zES*v}zi2OTgaMR`jjvDv*sQmzPfR7<=dd%c=jAVxf_J=Ou|;1q6Ql*{My(N!K6oF1 zk_7u9B~#uJnyu4IaSb$@w#uC83dP^%`P`&l=NN9*d^}%<oA8 zODD{Z%lIHsh#4)=pj;C9!Hev`v~> zXIF2$cdyHFbJ9Yos?D%Zk{`3X2BrL*;?WI!D{y?6(L<`zy;RsPtGV3&ezYYnB2h%Q zX`HHkGnV^RpDlnz3JXl~?AYCJHrI}}%;U$YJ3`Y!&vr!`${uKG8Y3~qnh2vDH=fFC z{z}xdP+Vz^JX2s4jec%yRj*InIHsqZQ?9%vIgaO`_nCiq<91eW|3tKc_XgF|H}u{M z>3%dGl<9{O5pL7g`rPug$;9ze#z!nKI*Wr!GQ%-XYu7Tbsae@W9H3HEbh~_=s=R=5 z(7EkU&AYJXa&cp3->9`sE5|5zy}LC1h`%T1&qBO$tXJYGRUpp#;v@bJ+=m-t=Sw_9 zT2w-TAQHvbl7%+52f`TJA`8vR$``;$YMg5q*r5bKDu!e>HY&;;=tI(>>K0Xj@5w!g3qTL#11E{XtmMK3*KRTmPGhEm{q0V!pe=hW>=eK! z!OJAE`)|&hGZO|17ei=5#2+B7baL76&Dawx&E?o`Z_WTOk?m8un~B{B6YKL_^%5nL z)#q=R0&}^mb}(ot`U@{~<4p3j>H>&oEy16RG$P@E1n z+;Ns(L&eBp4l(kaAvV&=-|xBXD;Q(Fs9uu}agXiY^TbnWdBKYnbinmB%5fp1&qh4Z zzoCCQoK>w^0LUj|Nosh@nfy8-&U>H5H@1b2NO)0#gf85$ureVuTbX{N!paWsDZw0w z^Q0thgy<|{)DwS5m=xKBeyz6DQZV1y;FBtc7)d`+&!?E$*c{AzjefP8n^*i2)TCeLx?Jo{D3MyI+U9-OVKT*#+e?3#Tl$QVzWV;q9+ zjCeB}Lzc>VAJwr?jP3lH!#(?HX<@IwX3n1^rF_WXWqD!10wR(FjTB!Eu8p5q2o z(Y9bwUQD6*B&9#^6|%WSW=sw6x`-^**e4#kWjYgGTxdm){MFpt*9xDxjdn#5ou+ER zdSox_Ry~ULK+v2*Heec5MTJVB&dk-ye0+9oh+UiC4cfLdqin6bkd>~AO@!t(7e^QUa;7OQ=X z!nfAZbXLW0N1_7#5?br&K&Byi18bTmU3!lMlo *si~8{sPK#a{>kH88iDo(>o#6 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 literal 0 HcmV?d00001 diff --git a/website/src/pages/404.mdx b/website/src/pages/404.mdx new file mode 100644 index 0000000..6d762a8 --- /dev/null +++ b/website/src/pages/404.mdx @@ -0,0 +1,7 @@ +--- +title: Not Found +--- + +import { NotFound } from 'smooth-doc' + + diff --git a/website/src/pages/docs/api-loadable-component.mdx b/website/src/pages/docs/api-loadable-component.mdx new file mode 100644 index 0000000..4c68735 --- /dev/null +++ b/website/src/pages/docs/api-loadable-component.mdx @@ -0,0 +1,87 @@ +--- +menu: API +title: '@loadable/component' +order: 10 +--- + +# @loadable/component + +## Loadable + +Create a loadable component. + +| Arguments | Description | +| ------------------ | ---------------------------------------- | +| `loadFn` | The function call to load the component. | +| `options` | Optional options. | +| `options.fallback` | Fallback displayed during the loading. | + +```js +import loadable from '@loadable/component' + +const OtherComponent = loadable(() => import('./OtherComponent')) +``` + +## Lazy + +Create a loadable component "Suspense" ready. + +| Arguments | Description | +| --------- | ---------------------------------------- | +| `loadFn` | The function call to load the component. | + +```js +import { lazy } from '@loadable/component' + +const OtherComponent = lazy(() => import('./OtherComponent')) +``` + +## LoadableComponent + +A component created using `loadable` or `lazy`. + +| Props | Description | +| ---------- | ------------------------------------------------- | +| `fallback` | Fallback displayed during the loading. | +| `...` | Props are forwarded as first argument of `loadFn` | + +## loadable.lib + +Create a loadable library. + +| Arguments | Description | +| ------------------ | ---------------------------------------- | +| `loadFn` | The function call to load the component. | +| `options` | Optional options. | +| `options.fallback` | Fallback displayed during the loading. | + +```js +import loadable from '@loadable/component' + +const Moment = loadable.lib(() => import('moment')) +``` + +## lazy.lib + +Create a loadable library "Suspense" ready. + +| Arguments | Description | +| --------- | ---------------------------------------- | +| `loadFn` | The function call to load the component. | + +```js +import { lazy } from '@loadable/component' + +const Moment = lazy.lib(() => import('moment')) +``` + +## LoadableLibrary + +A component created using `loadable.lib` or `lazy.lib`. + +| Props | Description | +| ---------- | ---------------------------------------------------- | +| `children` | Function called when the library is loaded. | +| `ref` | Accepts a ref, populated when the library is loaded. | +| `fallback` | Fallback displayed during the loading. | +| `...` | Props are forwarded as first argument of `loadFn` | diff --git a/website/src/pages/docs/api-loadable-server.mdx b/website/src/pages/docs/api-loadable-server.mdx new file mode 100644 index 0000000..4f21f82 --- /dev/null +++ b/website/src/pages/docs/api-loadable-server.mdx @@ -0,0 +1,124 @@ +--- +menu: API +title: '@loadable/server' +order: 20 +--- + +# @loadable/server + +## ChunkExtractor + +Used to collect chunks server-side and get them as script tags or script elements. + +| Arguments | Description | +| --------------------- | ----------------------------------------------------------- | +| `options` | An object options. | +| `options.statsFile` | Stats file path generated using `@loadable/webpack-plugin`. | +| `options.stats` | Stats generated using `@loadable/webpack-plugin`. | +| `options.entrypoints` | Webpack entrypoints to load (default to `["main"]`). | +| `options.outputPath` | Optional output path (only for `requireEntrypoint`). | + +You must specify either `statsFile` or `stats` to be able to use `ChunkExtractor`. + +Using `statsFile` will automatically reload stats for you if they change. + +```js +import { ChunkExtractor } from '@loadable/server' + +const statsFile = path.resolve('../dist/loadable-stats.json') +const chunkExtractor = new ChunkExtractor({ statsFile }) +``` + +## chunkExtractor.collectChunks + +Wrap your application in a `ChunkExtractorManager`. + +| Arguments | Description | +| --------- | ------------------------------------------------------------ | +| `element` | JSX element that will be wrapped in `ChunkExtractorManager`. | + +```js +const app = chunkExtractor.collectChunks() +``` + +## chunkExtractor.requireEntrypoint + +Require the entrypoint of your application as a commonjs module. + +| Arguments | Description | +| --------- | ---------------------------------------------------------------- | +| `name` | Optional name the entrypoint, default to the first one (`main`). | + +```js +const { default: App } = chunkExtractor.requireEntrypoint() +const app = +``` + +## chunkExtractor.getScriptTags + +Get scripts as a string of `