Skip to content

Commit

Permalink
Merge pull request #197 from theKashey/refactor-bundlesize
Browse files Browse the repository at this point in the history
Refactor structure
  • Loading branch information
theKashey authored Sep 9, 2020
2 parents fd7352b + d4c6cd2 commit 369579a
Show file tree
Hide file tree
Showing 27 changed files with 458 additions and 273 deletions.
4 changes: 2 additions & 2 deletions .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ module.exports = [
{
path: ['dist/es2015/entrypoints/index.js', 'dist/es2015/entrypoints/boot.js'],
ignore: ['tslib'],
limit: '3.7 KB',
limit: '3.9 KB',
},
{
path: 'dist/es2015/entrypoints/index.js',
ignore: ['tslib'],
limit: '3.5 KB',
limit: '3.6 KB',
},
{
path: 'dist/es2015/entrypoints/boot.js',
Expand Down
6 changes: 3 additions & 3 deletions .size.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
{
"name": "dist/es2015/entrypoints/index.js, dist/es2015/entrypoints/boot.js",
"passed": true,
"size": 3704
"size": 3975
},
{
"name": "dist/es2015/entrypoints/index.js",
"passed": true,
"size": 3414
"size": 3606
},
{
"name": "dist/es2015/entrypoints/boot.js",
"passed": true,
"size": 1863
"size": 1923
}
]
92 changes: 91 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

| Library | Suspense | SSR | Hooks | Library | Non-modules | import(`./${value}`) | babel-macro | webpack only |
| ------------------- | :------: | :-: | :---: | :-----: | :---------: | :------------------: | :---------: | :----------: |
| React.lazy ||||||| 😹 |
| React.lazy ||||||| 😹 | no-ssr |
| react-loadable |||||||| 😿 |
| @loadable/component |||||||| 😿 |
| imported-component |||||||| 😸 |
Expand Down Expand Up @@ -783,6 +783,96 @@ const prefetchChunks = (chunks, assets) =>
res.send(prefetchChunks(chunkNames, assets));
```

#### Preloading

Proper preloading is available **only** with bundler integration. Calling `component.preload` will not
only `preload` it, but will `execute` as well.

> `.preload` is equal do loading script as usual.
If you seek the best experience you might want to prefetch or preload only (network only), not load (network and CPU).

In order to prefetch(or preload) scripts - use `webpack-imported`, as seen in examples above.

You need SSR step in order to use preloading!

##### Step 1 - expose known chunks

In order to prefetch or preload you should know scripts locations. This information is stored inside webpack, and you cannot access it from user code.
As a result we have to duplicate this information:

```js
import { importAssets } from 'webpack-imported';
// react-imported-component data file
import applicationImports from '../async-requires';
// webpack-imported data file
import importedChunks from '../build/imported.json';
// 👆 this file is generated during the build, you cannot use it "IN" the build
// that's why this is Server Side only component

export const ScriptLocations = () => (
<script
dangerouslySetInnerHTML={{
__html: `
window.KNOWN_SCRIPT_MARKS = ${JSON.stringify(
applicationImports.reduce((acc, [, chunkName]) => {
if (chunkName) {
acc[chunkName] = importAssets(importedChunks, chunkName).raw.load;
}
return acc;
}, {})
)};
`,
}}
/>
);
```

Then add `<ScriptLocations/>` somewhere in your SSR-ed `head`.

##### Step 2 - preload

Then you will be able to `prefetch(() => import('./home')`.

```js
import { getMarkedChunks, loadableResource } from 'react-imported-component';

// this function is partially duplicating webpack internals
export const prefetch = importCallback => {
// get a "lodable" attached for a given import
const loadable = loadableResource(importCallback);
if (typeof document !== 'undefined') {
const prefix = __webpack_public_path__;
if (loadable) {
// get chunks used in loadable
const chunks = getMarkedChunks(loadable.mark);
chunks.forEach(chunk => {
// note the usage of KNOWN_SCRIPT_MARKS
const { js = [], css = [] } = window.KNOWN_SCRIPT_MARKS[chunk];
js.forEach(script => {
const link = document.createElement('link');

link.rel = 'prefetch';
link.as = 'script';

link.href = prefix + script;
document.head.appendChild(link);
});
css.forEach(style => {
const link = document.createElement('link');

link.rel = 'prefetch';
link.as = 'style';

link.href = prefix + style;
document.head.appendChild(link);
});
});
}
}
};
```

### Parcel integration

Use `parcel-manifest` and `getMarkedFileNames`(instead of `getMarkedChunks`) to find which files were required and has to be imported.
Expand Down
2 changes: 1 addition & 1 deletion __tests__/componentLoader.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import '@theuiteam/lib-builder/configs/setupEnzyme';
import { mount } from 'enzyme';
import * as React from 'react';

import { toLoadable } from '../src/loadable/loadable';
import { toLoadable } from '../src/loadable/toLoadable';
import { ImportedComponent } from '../src/ui/Component';
import loader from '../src/ui/HOC';

Expand Down
2 changes: 1 addition & 1 deletion __tests__/module.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { mount } from 'enzyme';
import * as React from 'react';
import { act } from 'react-dom/test-utils';

import { done } from '../src/loadable/loadable';
import { done } from '../src/loadable/pending';
import { importedModule, ImportedModule } from '../src/ui/Module';

describe('Module Component', () => {
Expand Down
6 changes: 4 additions & 2 deletions __tests__/rehydrate.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import * as ReactDOM from 'react-dom/server';
import { act } from 'react-dom/test-utils';

import { setConfiguration } from '../src/configuration/config';
import { done as whenDone, toLoadable } from '../src/loadable/loadable';
import { createLoadableStream, drainHydrateMarks, rehydrateMarks } from '../src/loadable/marks';
import { drainHydrateMarks, rehydrateMarks } from '../src/loadable/marks';
import { done as whenDone } from '../src/loadable/pending';
import { createLoadableStream } from '../src/loadable/stream';
import { toLoadable } from '../src/loadable/toLoadable';
import { ImportedComponent } from '../src/ui/Component';
import { ImportedStream } from '../src/ui/context';
import imported from '../src/ui/HOC';
Expand Down
38 changes: 34 additions & 4 deletions __tests__/useImported.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import * as React from 'react';
import { useEffect, useState } from 'react';

import { act } from 'react-dom/test-utils';
import { drainHydrateMarks } from '../src/entrypoints';
import { done, getLoadable, toLoadable } from '../src/loadable/loadable';
import { DefaultImport, drainHydrateMarks } from '../src/entrypoints';
import { getLoadable } from '../src/loadable/loadable';
import { done } from '../src/loadable/pending';
import { toLoadable } from '../src/loadable/toLoadable';
import { useImported } from '../src/ui/useImported';

const importedWrapper = (_: any, b: any) => b;
const importedWrapper = <T extends any>(_: any, b: T): T => b;

jest.mock('../src/utils/detectBackend', () => ({ isBackend: false }));

Expand Down Expand Up @@ -122,6 +124,34 @@ describe('useImported', () => {
// expect().toEqual(['unconditional-mark']);
});

it('named import', async () => {
const importer = () =>
importedWrapper('imported_unconditional-mark_component', Promise.resolve({ named: () => <span>loaded!</span> }));

const Comp = () => {
const { loading, imported: Component } = useImported(importer, ({ named }) => named);

if (Component) {
return <Component />;
}

if (loading) {
return <span>loading</span>;
}
return <span>nothing</span>;
};

const wrapper = mount(<Comp />);
expect(wrapper.html()).toContain('loading');

await act(async () => {
await Promise.resolve();
});

expect(wrapper.update().html()).toContain('loaded!');
expect(drainHydrateMarks()).toEqual(['unconditional-mark']);
});

it('unconditional import', async () => {
const importer = () =>
importedWrapper('imported_unconditional-mark_component', Promise.resolve(() => <span>loaded!</span>));
Expand Down Expand Up @@ -225,7 +255,7 @@ describe('useImported', () => {
const importer = () => () => <span>loaded!</span>;

const Comp = () => {
const { loading, imported: Component } = useImported(importer as any);
const { loading, imported: Component } = useImported((importer as any) as DefaultImport<React.FC>);

if (Component) {
return <Component />;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-imported-component",
"version": "6.3.11",
"version": "6.3.12",
"description": "I will import your component, and help to handle it",
"main": "dist/es5/entrypoints/index.js",
"jsnext:main": "dist/es2015/entrypoints/index.js",
Expand Down
3 changes: 2 additions & 1 deletion src/entrypoints/boot.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { setConfiguration } from '../configuration/config';
import { assignImportedComponents, done as whenComponentsReady } from '../loadable/loadable';
import { assignImportedComponents } from '../loadable/assignImportedComponents';
import { loadByChunkname } from '../loadable/loadByChunkName';
import { rehydrateMarks } from '../loadable/marks';
import { done as whenComponentsReady } from '../loadable/pending';
import { addPreloader } from '../loadable/preloaders';
import { injectLoadableTracker } from '../trackers/globalTracker';

Expand Down
15 changes: 8 additions & 7 deletions src/entrypoints/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { setConfiguration } from '../configuration/config';
import { configure, ImportedConfiguration } from '../configuration/configuration';
import {
assignImportedComponents,
clearImportedCache,
done as whenComponentsReady,
dryRender,
getLoadable as loadableResource,
} from '../loadable/loadable';
import { assignImportedComponents } from '../loadable/assignImportedComponents';
import { clearImportedCache, dryRender, getLoadable as loadableResource } from '../loadable/loadable';
import { loadByChunkname } from '../loadable/loadByChunkName';
import { getMarkedChunks, getMarkedFileNames } from '../loadable/markerMapper';
import { drainHydrateMarks, printDrainHydrateMarks, rehydrateMarks, waitForMarks } from '../loadable/marks';
import { done as whenComponentsReady } from '../loadable/pending';
import { addPreloader } from '../loadable/preloaders';
import { DefaultImport } from '../types';
import { ImportedComponent } from '../ui/Component';
import { ImportedComponent as ComponentLoader } from '../ui/Component';
import { ImportedStream } from '../ui/context';
Expand Down Expand Up @@ -43,8 +41,11 @@ export {
useImported,
useLazy,
addPreloader,
getMarkedChunks,
getMarkedFileNames,
clearImportedCache,
ImportedConfiguration,
configure,
DefaultImport,
};
export default imported;
2 changes: 1 addition & 1 deletion src/entrypoints/macro.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @ts-ignore
import { createMacro } from 'babel-plugin-macros';
import { createTransformer } from '../babel/babel';
import { assignImportedComponents } from '../loadable/loadable';
import { assignImportedComponents } from '../loadable/assignImportedComponents';

function getMacroType(tagName: string) {
switch (tagName) {
Expand Down
3 changes: 2 additions & 1 deletion src/entrypoints/server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { setConfiguration } from '../configuration/config';
import { getMarkedChunks, getMarkedFileNames } from '../loadable/markerMapper';
import { createLoadableStream, drainHydrateMarks, printDrainHydrateMarks } from '../loadable/marks';
import { drainHydrateMarks, printDrainHydrateMarks } from '../loadable/marks';
import { createLoadableStream } from '../loadable/stream';
import { getLoadableTrackerCallback } from '../trackers/globalTracker';
import { createLoadableTransformer } from '../transformers/loadableTransformer';
import { ImportedStream } from '../ui/context';
Expand Down
28 changes: 28 additions & 0 deletions src/loadable/assignImportedComponents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { settings } from '../configuration/config';
import { Promised } from '../types';
import { assignMetaData } from './metadata';
import { done } from './pending';
import { LOADABLE_SIGNATURE } from './registry';
import { toLoadable } from './toLoadable';

type ImportedDefinition = [Promised<any>, string, string, boolean];
/**
* to be used __only via CLI tools__
*/
export const assignImportedComponents = (set: ImportedDefinition[]) => {
const countBefore = LOADABLE_SIGNATURE.size;
set.forEach(imported => {
const allowAutoLoad = !(imported[3] || !settings.fileFilter(imported[2]));
const loadable = toLoadable(imported[0], allowAutoLoad);
assignMetaData(loadable.mark, loadable, imported[1], imported[2]);
});

if (countBefore === LOADABLE_SIGNATURE.size) {
// tslint:disable-next-line:no-console
console.error('react-imported-component: no import-marks found, please check babel plugin');
}

done();

return set;
};
2 changes: 1 addition & 1 deletion src/loadable/loadByChunkName.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { markMeta } from './loadable';
import { markMeta } from './metadata';

/**
* loads chunk by a known chunkname
Expand Down
Loading

0 comments on commit 369579a

Please sign in to comment.