UNPKG

3 kBPlain TextView Raw
1import {WebpackStore} from './webpack-store';
2
3export interface HotModuleReplacementOptions {
4 LOCALSTORAGE_KEY?: string;
5 localStorage?: boolean;
6 storeToken?: any;
7 globalDispose?: string;
8
9 getState?: Function;
10 data?: any;
11}
12
13export function hotModuleReplacement(bootloader: Function, module: any, options: HotModuleReplacementOptions = {}) {
14 const LOCALSTORAGE_KEY = options.LOCALSTORAGE_KEY || '@@WEBPACK_INITIAL_DATA';
15 const LOCAL = options.localStorage || false;
16 const TOKEN = options.storeToken || WebpackStore;
17 const DISPOSE = options.globalDispose || 'WEBPACK_HMR_beforeunload';
18 const GET_STATE = options.getState || getState;
19 let DATA = options.data || module.hot.data.state;
20 let COMPONENT_REF = null;
21 let disposed = false;
22
23 function getState(appState) {
24 const json = appState.toJSON();
25
26 if (LOCAL) {
27 console.time('localStorage');
28 localStorage.setItem(LOCALSTORAGE_KEY, JSON.stringify(appState));
29 console.timeEnd('localStorage');
30 }
31 return json;
32 }
33
34 console.log('DATA', DATA);
35 if (!DATA && LOCAL) {
36 try {
37 console.time('start localStorage');
38 DATA = JSON.parse(localStorage.getItem(LOCALSTORAGE_KEY)) || DATA;
39 console.timeEnd('start localStorage');
40 } catch (e) {
41 console.log('JSON.parse Error', e);
42 }
43 }
44 console.time('bootstrap');
45 if (document.readyState === 'complete') {
46 bootloader(DATA)
47 .then((cmpRef: any) => COMPONENT_REF = cmpRef)
48 .then((cmpRef => (console.timeEnd('bootstrap'), cmpRef)));
49 } else {
50 document.addEventListener('DOMContentLoaded', () => {
51 bootloader(DATA)
52 .then((cmpRef: any) => COMPONENT_REF = cmpRef)
53 .then((cmpRef => (console.timeEnd('bootstrap'), cmpRef)));
54 });
55 }
56
57
58
59 function beforeunload(event) {
60 const appState = COMPONENT_REF.injector.get(TOKEN);
61 return GET_STATE(appState);
62 }
63 (<any>window)[DISPOSE] = () => {
64 disposed = true;
65 window.removeEventListener('beforeunload', beforeunload);
66 if (LOCAL) {
67 localStorage.removeItem(LOCALSTORAGE_KEY);
68 }
69 };
70
71 module.hot.accept();
72
73 window.addEventListener('beforeunload', beforeunload);
74
75 module.hot.dispose((data: any) => {
76 console.time('dispose');
77 const componentNode = COMPONENT_REF.location.nativeElement;
78 const newNode = document.createElement(componentNode.tagName);
79 // display none
80 const currentDisplay = newNode.style.display;
81 newNode.style.display = 'none';
82 const parentNode = componentNode.parentNode;
83 parentNode.insertBefore(newNode, componentNode);
84
85 const appState = COMPONENT_REF.injector.get(TOKEN);
86 const json = GET_STATE(appState);
87
88 data.state = json;
89
90 COMPONENT_REF.dispose();
91
92 newNode.style.display = currentDisplay;
93
94 if (!disposed) {
95 window.removeEventListener('beforeunload', beforeunload);
96 }
97 disposed = true;
98 console.timeEnd('dispose');
99 });
100}