@zohodesk/react-cli 0.0.1-beta.99 → 0.0.1-betaa.138.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (202) hide show
  1. package/.eslintignore +7 -7
  2. package/.eslintrc.js +183 -183
  3. package/CHANGELOG.md +5 -0
  4. package/README.md +636 -491
  5. package/bin/cli.js +372 -367
  6. package/files/eslintrc.js +57 -0
  7. package/files/prettierrc.js +3 -0
  8. package/lib/babel/cmjs-plugins-presets.js +16 -9
  9. package/lib/babel/es-plugins-presets.js +26 -14
  10. package/lib/common/getEntries.js +31 -22
  11. package/lib/common/getPublicPathConfig.js +27 -13
  12. package/lib/common/index.js +21 -25
  13. package/lib/common/splitChunks.js +62 -53
  14. package/lib/common/templateParameters.js +10 -8
  15. package/lib/configs/jest.config.js +15 -25
  16. package/lib/configs/webpack.component.umd.config.js +31 -37
  17. package/lib/configs/webpack.css.umd.config.js +44 -47
  18. package/lib/configs/webpack.dev.config.js +70 -52
  19. package/lib/configs/webpack.docs.config.js +106 -106
  20. package/lib/configs/webpack.prod.config.js +95 -75
  21. package/lib/hooks/docsProptypeHook.js +32 -38
  22. package/lib/jest/commitedFilesResult.js +103 -74
  23. package/lib/jest/coverageCollector.js +41 -21
  24. package/lib/jest/jsonMaker.js +15 -16
  25. package/lib/jest/preProcessors/cssPreprocessor.js +16 -18
  26. package/lib/jest/preProcessors/jsPreprocessor.js +3 -5
  27. package/lib/jest/preProcessors/otherFilesPreprocessor.js +5 -6
  28. package/lib/jest/result.js +90 -45
  29. package/lib/jest/run.js +43 -43
  30. package/lib/jest/setup.js +102 -95
  31. package/lib/loaderUtils/getCSSLoaders.js +21 -22
  32. package/lib/loaderUtils/getDevJsLoaders.js +25 -23
  33. package/lib/loaderUtils/index.js +11 -13
  34. package/lib/loaders/docsLoader.js +15 -15
  35. package/lib/loaders/docsPropsLoader.js +14 -17
  36. package/lib/loaders/fileLoader.js +33 -35
  37. package/lib/loaders/scriptInstrumentLoader.js +21 -20
  38. package/lib/loaders/workerLoader.js +136 -0
  39. package/lib/middlewares/HMRMiddleware.js +54 -45
  40. package/lib/middlewares/SSTMiddleware.js +8 -5
  41. package/lib/pluginUtils/getDevPlugins.js +114 -52
  42. package/lib/pluginUtils/getDocsPlugins.js +25 -29
  43. package/lib/pluginUtils/getLibraryPlugins.js +8 -10
  44. package/lib/pluginUtils/getProdPlugins.js +163 -74
  45. package/lib/pluginUtils/getServerPlugins.js +8 -11
  46. package/lib/pluginUtils/getUMDCSSPlugins.js +11 -15
  47. package/lib/pluginUtils/getUMDComponentPlugins.js +11 -15
  48. package/lib/pluginUtils/index.js +36 -43
  49. package/lib/plugins/CdnChangePlugin.js +63 -0
  50. package/lib/plugins/CleanupStatsPlugin.js +18 -32
  51. package/lib/plugins/CustomAttributePlugin.js +79 -0
  52. package/lib/plugins/CustomAttributePlugin.md +35 -0
  53. package/lib/plugins/EFCPlugin.js +185 -0
  54. package/lib/plugins/I18NInjectIntoIndexPlugin.js +118 -52
  55. package/lib/plugins/I18nSplitPlugin/I18nDebugPlugin.js +60 -0
  56. package/lib/plugins/I18nSplitPlugin/I18nDependency.js +44 -0
  57. package/lib/plugins/I18nSplitPlugin/I18nDownlodLogic.js +266 -0
  58. package/lib/plugins/I18nSplitPlugin/I18nFilesEmitter.js +183 -0
  59. package/lib/plugins/I18nSplitPlugin/I18nKeysIdentifer.js +100 -0
  60. package/lib/plugins/I18nSplitPlugin/I18nSplit.md +86 -0
  61. package/lib/plugins/I18nSplitPlugin/README.md +25 -0
  62. package/lib/plugins/I18nSplitPlugin/index.js +185 -0
  63. package/lib/plugins/I18nSplitPlugin/utils/collectI18nKeys.js +64 -0
  64. package/lib/plugins/I18nSplitPlugin/utils/getI18nFileUrlPathTemplate.js +13 -0
  65. package/lib/plugins/I18nSplitPlugin/utils/getI18nKeysFormModules.js +26 -0
  66. package/lib/plugins/I18nSplitPlugin/utils/hashUtils.js +40 -0
  67. package/lib/plugins/I18nSplitPlugin/utils/index.js +31 -0
  68. package/lib/plugins/I18nSplitPlugin/utils/propertiesUtils.js +112 -0
  69. package/lib/plugins/ManifestPlugin.js +52 -63
  70. package/lib/plugins/ModuleStatsPlugin.js +83 -173
  71. package/lib/plugins/OptimizeJSPlugin.js +24 -41
  72. package/lib/plugins/PublicPathCallbackPlugin.js +42 -116
  73. package/lib/plugins/PublicPathChangePlugin.js +175 -284
  74. package/lib/plugins/ReportGeneratePlugin.js +150 -151
  75. package/lib/plugins/ResourceHintsPlugin.js +53 -35
  76. package/lib/plugins/ScriptInstrumentPlugin.js +22 -37
  77. package/lib/plugins/ServiceWorkerPlugin.js +81 -57
  78. package/lib/plugins/ShadowDOMSupportPlugin.js +153 -234
  79. package/lib/plugins/SourceMapHookPlugin.js +21 -33
  80. package/lib/plugins/TPHashMappingPlugin.js +67 -0
  81. package/lib/plugins/UglifyCSSPlugin.js +23 -30
  82. package/lib/plugins/UnusedFilesFindPlugin.js +137 -152
  83. package/lib/plugins/index.js +100 -91
  84. package/lib/plugins/webpackwatchrunplugin.js +18 -30
  85. package/lib/postcss-plugins/ExcludeRTLPlugin.js +14 -17
  86. package/lib/schemas/index.js +336 -81
  87. package/lib/servers/clusterHubServer.js +22 -26
  88. package/lib/servers/docsServer.js +3 -5
  89. package/lib/servers/docsServerCore.js +84 -91
  90. package/lib/servers/helpServer.js +19 -21
  91. package/lib/servers/impactServer.js +99 -92
  92. package/lib/servers/mockserver.js +24 -24
  93. package/lib/servers/scrServer.js +78 -98
  94. package/lib/servers/server.js +101 -122
  95. package/lib/servers/ssServer.js +63 -61
  96. package/lib/sh/pre-commit.sh +34 -34
  97. package/lib/sh/reportPublish.sh +45 -46
  98. package/lib/templates/CoverageScriptTemplate.js +45 -18
  99. package/lib/templates/WMSTemplate.js +17 -18
  100. package/lib/templates/linterConstant.js +6 -4
  101. package/lib/utils/babelPresets.js +12 -5
  102. package/lib/utils/buildstats.html +148 -148
  103. package/lib/utils/clean.js +12 -11
  104. package/lib/utils/copy.js +12 -34
  105. package/lib/utils/copyTimezones.js +9 -16
  106. package/lib/utils/createEventStream.js +24 -19
  107. package/lib/utils/cssClassNameGenerate.js +44 -73
  108. package/lib/utils/cssURLReplacer.js +60 -54
  109. package/lib/utils/dependencyPostPublish.js +20 -19
  110. package/lib/utils/fileUtils.js +66 -54
  111. package/lib/utils/folderIterator.js +20 -21
  112. package/lib/utils/getComponents.js +70 -27
  113. package/lib/utils/getCurrentBranch.js +11 -17
  114. package/lib/utils/getDependenciesImpactList.js +114 -187
  115. package/lib/utils/getHash.js +9 -13
  116. package/lib/utils/getIp.js +9 -9
  117. package/lib/utils/getOptions.js +26 -29
  118. package/lib/utils/getServerURL.js +19 -10
  119. package/lib/utils/index.js +147 -126
  120. package/lib/utils/init.js +2 -2
  121. package/lib/utils/initPreCommitHook.js +40 -32
  122. package/lib/utils/jsonHelper.js +37 -21
  123. package/lib/utils/lint/addScripts.js +27 -0
  124. package/lib/utils/lint/checkExistingConfig.js +67 -0
  125. package/lib/utils/lint/copyConfigs.js +24 -0
  126. package/lib/utils/lint/index.js +54 -0
  127. package/lib/utils/lint/lintScripts.js +11 -0
  128. package/lib/utils/lint/lintSetup.js +31 -0
  129. package/lib/utils/lint/lintStagedPreCommitHook.js +7 -0
  130. package/lib/utils/lint/question.js +30 -0
  131. package/lib/utils/lintReporter.js +70 -56
  132. package/lib/utils/mailSender.js +12 -27
  133. package/lib/utils/pullOrigin.js +21 -18
  134. package/lib/utils/reinstallDependencies.js +76 -85
  135. package/lib/utils/removeAttributes.js +25 -23
  136. package/lib/utils/repoClone.js +47 -45
  137. package/lib/utils/request.js +64 -77
  138. package/lib/utils/resultSchema.json +73 -73
  139. package/lib/utils/rtl.js +22 -29
  140. package/lib/utils/setEnvVariables.js +5 -6
  141. package/lib/utils/ssTestHack.js +21 -19
  142. package/lib/utils/switchBranch.js +21 -20
  143. package/lib/utils/urlConcat.js +22 -0
  144. package/package.json +141 -136
  145. package/templates/app/.eslintrc.js +140 -140
  146. package/templates/app/README.md +12 -12
  147. package/templates/app/app/index.html +24 -24
  148. package/templates/app/app/properties/ApplicationResources_en_US.properties +1 -1
  149. package/templates/app/app/properties/i18nkeys.json +3 -3
  150. package/templates/app/docs/all.html +69 -69
  151. package/templates/app/mockapi/index.js +18 -18
  152. package/templates/app/package.json +37 -37
  153. package/templates/app/src/actions/SampleActions/index.js +37 -37
  154. package/templates/app/src/actions/index.js +65 -65
  155. package/templates/app/src/appUrls.js +19 -19
  156. package/templates/app/src/components/Alert/Alert.js +134 -134
  157. package/templates/app/src/components/Alert/Alert.module.css +79 -79
  158. package/templates/app/src/components/FreezeLayer/FreezeLayer.css +37 -37
  159. package/templates/app/src/components/FreezeLayer/FreezeLayer.js +84 -84
  160. package/templates/app/src/components/Sample/Sample.module.css +11 -11
  161. package/templates/app/src/components/Sample/SampleList.js +61 -61
  162. package/templates/app/src/components/Slider/Slider.css +41 -41
  163. package/templates/app/src/components/Slider/Slider.js +55 -55
  164. package/templates/app/src/containers/AlertContainer/index.js +15 -15
  165. package/templates/app/src/containers/AppContainer/index.js +96 -96
  166. package/templates/app/src/containers/AppContainer/index.module.css +27 -27
  167. package/templates/app/src/containers/CustomMatch/index.js +65 -65
  168. package/templates/app/src/containers/DevTools/index.js +10 -10
  169. package/templates/app/src/containers/Header/index.js +67 -67
  170. package/templates/app/src/containers/Header/index.module.css +43 -43
  171. package/templates/app/src/containers/Redirect/index.js +63 -63
  172. package/templates/app/src/containers/Redirector/index.js +47 -47
  173. package/templates/app/src/containers/SampleListContainer/ListContainer.js +42 -42
  174. package/templates/app/src/containers/SampleListContainer/ListContainer.module.css +3 -3
  175. package/templates/app/src/historyChange.js +5 -5
  176. package/templates/app/src/index.html +10 -10
  177. package/templates/app/src/index.js +24 -24
  178. package/templates/app/src/middleware/PromiseMiddleware.js +59 -59
  179. package/templates/app/src/reducers/alertData.js +11 -11
  180. package/templates/app/src/reducers/index.js +6 -6
  181. package/templates/app/src/reducers/samples.js +19 -19
  182. package/templates/app/src/store/configureStore.dev.js +51 -51
  183. package/templates/app/src/store/configureStore.js +5 -5
  184. package/templates/app/src/store/configureStore.prod.js +26 -26
  185. package/templates/app/src/util/Common.js +5 -5
  186. package/templates/app/src/util/RequestAPI.js +132 -132
  187. package/templates/docs/all.html +249 -249
  188. package/templates/docs/component.html +178 -178
  189. package/templates/docs/components.html +221 -221
  190. package/templates/docs/css/b.min.css +6 -6
  191. package/templates/docs/css/component.css +42 -42
  192. package/templates/docs/css/componentTest.css +6 -6
  193. package/templates/docs/css/hopscotch.css +585 -585
  194. package/templates/docs/css/style.css +1022 -1022
  195. package/templates/docs/index.html +1493 -1493
  196. package/templates/docs/js/active-line.js +72 -72
  197. package/templates/docs/js/b.min.js +7 -7
  198. package/templates/docs/js/codemirror.js +9680 -9680
  199. package/templates/docs/js/designTokens.js +334 -334
  200. package/templates/docs/js/j.min.js +4 -4
  201. package/templates/docs/js/javascript.js +874 -874
  202. package/templates/docs/js/matchbrackets.js +145 -145
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _webpackSources = require("webpack-sources");
9
+
10
+ var _utils = require("./utils");
11
+
12
+ var _getI18nKeysFormModules = _interopRequireDefault(require("./utils/getI18nKeysFormModules"));
13
+
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+
16
+ /**
17
+ * this plugin was creating the chunk specific i18n chunk's.
18
+ */
19
+ // this plugin's kick starter is apply method
20
+ const pluginName = 'I18nFilesEmitter';
21
+ const MODULE_TYPE = 'json/i18n';
22
+
23
+ const i18ntype = locale => `${MODULE_TYPE}/${locale}`;
24
+
25
+ class I18nFilesEmitter {
26
+ constructor({
27
+ allI18nObject,
28
+ i18nManifestFileName,
29
+ filenameTemplate,
30
+ locales,
31
+ jsonpFunc
32
+ }) {
33
+ this.locales = locales;
34
+ this.allI18nObject = allI18nObject;
35
+ this.filenameTemplate = filenameTemplate; // this.filenameTemplate = "i18n-chunk/[locale]/[name].js"
36
+
37
+ this.jsonpFunc = jsonpFunc;
38
+ this.prevHashes = {};
39
+ this.i18nManifestFileName = i18nManifestFileName;
40
+ }
41
+
42
+ emitAsset(compilation, filename, source, info) {
43
+ // NOTE: info support available since webpack v4.40.0 https://webpack.js.org/api/stats/#asset-objects
44
+ if (!compilation.emitAsset) {
45
+ compilation.assets[filename] = source;
46
+ } else {
47
+ compilation.emitAsset(filename, source, info);
48
+ }
49
+ } // this method for create object and assign value for i18nkeys
50
+
51
+
52
+ getI18nObjectByLocale(i18nKeys, locale) {
53
+ const data = {};
54
+ i18nKeys.forEach(key => {
55
+ data[key] = this.allI18nObject[locale][key];
56
+ });
57
+ return data;
58
+ }
59
+
60
+ getTemplateString(i18nKeys, locale) {
61
+ let i18nObject = this.getI18nObjectByLocale(i18nKeys, locale);
62
+ return `${this.jsonpFunc}(${(0, _utils.jsonToString)(i18nObject)});`; // return `${this.jsonpFunc}(JSON.parse(${JSON.stringify(jsonToString(i18nObject))}));`;
63
+ }
64
+
65
+ renderI18nLocaleChunk(chunk, locale, i18nKeys) {
66
+ // renderI18nLocaleChunk(chunk, locale, i18nKeys, compilation) {
67
+ const filenameTemplate = this.filenameTemplate.replace(/\[locale\]/g, locale);
68
+ const pathOptions = {
69
+ chunk,
70
+ contentHashType: i18ntype(locale)
71
+ };
72
+ return {
73
+ render: () => new _webpackSources.RawSource(this.getTemplateString(i18nKeys, locale)),
74
+ filenameTemplate,
75
+ pathOptions,
76
+ identifier: `${pluginName}.${chunk.id}.${locale}`,
77
+ hash: chunk.contentHash[i18ntype(locale)]
78
+ };
79
+ }
80
+
81
+ emitI18nFilesForChunk(chunk, compilation) {
82
+ const i18nKeys = (0, _getI18nKeysFormModules.default)(chunk.modulesIterable);
83
+ const manifestForChunk = {
84
+ assets: {},
85
+ hasI18n: false,
86
+ hasChanges: false
87
+ };
88
+
89
+ if (!i18nKeys.length) {
90
+ // why it is not checked as 0
91
+ return manifestForChunk;
92
+ }
93
+
94
+ manifestForChunk.hasI18n = true; // const locales = ['en_US'];
95
+
96
+ this.locales.forEach(locale => {
97
+ const result = this.renderI18nLocaleChunk(chunk, locale, i18nKeys, compilation);
98
+ const {
99
+ filenameTemplate,
100
+ pathOptions,
101
+ render,
102
+ identifier,
103
+ hash
104
+ } = result;
105
+ const filePath = compilation.getPath(filenameTemplate, pathOptions);
106
+ manifestForChunk.assets[locale] = filePath;
107
+
108
+ if (this.prevHashes[identifier] === hash) {
109
+ return;
110
+ }
111
+
112
+ manifestForChunk.hasChanges = true;
113
+ this.prevHashes[identifier] = hash;
114
+ this.emitAsset(compilation, filePath, render(), {
115
+ locale,
116
+ chunkId: chunk.id,
117
+ chunkName: chunk.name
118
+ }); // compilation.assets[filePath] = render();
119
+ });
120
+ return manifestForChunk;
121
+ }
122
+
123
+ emitI18nAssert(compilation) {
124
+ let manifest = {};
125
+ let needEmitManifest = false;
126
+ compilation.chunks.forEach(chunk => {
127
+ const manifestForChunk = this.emitI18nFilesForChunk(chunk, compilation);
128
+
129
+ if (manifestForChunk.hasI18n) {
130
+ manifest[chunk.id] = manifestForChunk.assets;
131
+ needEmitManifest = needEmitManifest || manifestForChunk.hasChanges;
132
+ }
133
+ });
134
+
135
+ if (needEmitManifest) {
136
+ const manifestSource = new _webpackSources.RawSource(JSON.stringify(manifest));
137
+ this.emitAsset(compilation, this.i18nManifestFileName, manifestSource, {
138
+ desc: 'this file is has chunks-locales-assets mapping'
139
+ });
140
+ }
141
+ }
142
+
143
+ apply(compiler) {
144
+ /*
145
+ compiler.hooks.thisCompilation.tap(pluginName, compilation => {
146
+ compilation.mainTemplate.hooks.renderManifest.tap(
147
+ pluginName,
148
+ (result, { chunk }) => {
149
+ this.renderChunk(result, compilation, chunk);
150
+ }
151
+ );
152
+ compilation.chunkTemplate.hooks.renderManifest.tap(
153
+ pluginName,
154
+ (result, { chunk }) => {
155
+ this.renderChunk(result, compilation, chunk);
156
+ }
157
+ );
158
+ });
159
+ */
160
+ // this below hook was tapped for create asssets(file) for chunk specific i18nChunk Files
161
+ compiler.hooks.emit.tap(pluginName, compilation => {
162
+ this.emitI18nAssert(compilation);
163
+ });
164
+ }
165
+ /*
166
+ renderChunk(result, compilation, chunk) {
167
+ const i18nKeys = getI18nKeysFormModules(chunk.modulesIterable);
168
+ // TODO: need to discuss with vimal ji can we chose this place for add i18n locale files ????
169
+ // IDEA: we chose this place for add i18n locale files ????
170
+ if (i18nKeys.length > 0) {
171
+ Object.keys(this.allI18nObject).forEach(locale => {
172
+ result.push(
173
+ this.renderI18nLocaleChunk(chunk, locale, i18nKeys, compilation)
174
+ );
175
+ });
176
+ }
177
+ }
178
+ */
179
+
180
+
181
+ }
182
+
183
+ exports.default = I18nFilesEmitter;
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _utils = require("./utils");
9
+
10
+ var _I18nDependency = require("./I18nDependency");
11
+
12
+ var _NullFactory = _interopRequireDefault(require("webpack/lib/NullFactory"));
13
+
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+
16
+ const pluginName = 'I18nKeysIdentifer';
17
+ /**
18
+ * this plugin search the i18 keys and make it as I18nDependency.
19
+ * how it works?
20
+ * this plugin get jsResourceI18nKeys in constructor.
21
+ * we walk throught the js files AST
22
+ * if any string literal in that AST is in jsResourceI18nKeys then we consider that string as I18n key
23
+ * after the walk of AST we get some I18n keys
24
+ * then we make it as I18nDependency.
25
+ */
26
+
27
+ class I18nKeysIdentifer {
28
+ constructor(jsResourceI18nKeys) {
29
+ this.jsResourceI18nKeys = jsResourceI18nKeys;
30
+ }
31
+
32
+ defineConfigarationForI18nDependency(compilation) {
33
+ compilation.dependencyFactories.set(_I18nDependency.I18nDependency, new _NullFactory.default());
34
+ compilation.dependencyTemplates.set(_I18nDependency.I18nDependency, new _I18nDependency.I18nDependencyTemplate());
35
+ }
36
+
37
+ addI18nDependency(module, i18nKeys) {
38
+ const identifier = `i18n ${module.resource}`;
39
+ const dep = new _I18nDependency.I18nDependency({
40
+ identifier,
41
+ i18nKeys
42
+ }, module.context, 0);
43
+ module.addDependency(dep); // console.log('module', i18nKeys, identifier);
44
+ }
45
+
46
+ apply(compiler) {
47
+ compiler.hooks.thisCompilation.tap(pluginName, (compilation, params) => {
48
+ // this below hook was tapped for we use I18nDependency
49
+ // so we must define module factory for I18nDependency
50
+ // and we must define how it import statement look like I18nDependencyTemplate
51
+ this.defineConfigarationForI18nDependency(compilation); // handler for parser
52
+
53
+ let handler = parser => {
54
+ parser.hooks.program.tap(pluginName, (ast, commmets) => {
55
+ const {
56
+ module
57
+ } = parser.state; //
58
+
59
+ if (!(module && /\.jsx?$/.test(module.resource))) {
60
+ return;
61
+ } // i18n grep proper contract regex
62
+
63
+
64
+ let i18nKeys = (0, _utils.collectI18nKeysfromAST)(ast, this.jsResourceI18nKeys);
65
+ i18nKeys = i18nKeys.concat( // i18n grep proper contract regex
66
+ (0, _utils.collectI18nKeysfromComments)(commmets, this.jsResourceI18nKeys));
67
+
68
+ if (i18nKeys.length) {
69
+ // console.log(
70
+ // 'i18nKeys.length',
71
+ // module.resource,
72
+ // i18nKeys.length < 5 ? i18nKeys : i18nKeys.length
73
+ // );
74
+ this.addI18nDependency(module, i18nKeys);
75
+ }
76
+ });
77
+ }; // this below hook was tapped for collect I18n Key from files and add as Deppenensy
78
+
79
+
80
+ const factory = params.normalModuleFactory;
81
+ factory.hooks.parser.for('javascript/auto').tap(pluginName, handler);
82
+ factory.hooks.parser.for('javascript/dynamic').tap(pluginName, handler);
83
+ });
84
+ }
85
+
86
+ }
87
+
88
+ exports.default = I18nKeysIdentifer;
89
+
90
+ I18nKeysIdentifer.isChunkHasI18n = function (chunk) {
91
+ for (const module of chunk.modulesIterable) {
92
+ for (const dep of module.dependencies) {
93
+ if (dep instanceof _I18nDependency.I18nDependency) {
94
+ return true;
95
+ }
96
+ }
97
+ }
98
+
99
+ return false;
100
+ };
@@ -0,0 +1,86 @@
1
+ # I18n Split As Chunks Plugin
2
+
3
+ generaly we have manage our all I18n keys and values as language specific i18n files and then we download all i18n in initial page load.
4
+
5
+ ### what is the problem with this?.
6
+ the problem is i18n file keep get's grown it will affect the the inital page load and critial rendering path.
7
+ So, We have decide to create a plugin for split i18n per chunk's of js vise.
8
+
9
+ ### what is i18n split?
10
+ it is like code split for i18n.
11
+ we will collect i18n from js chunk and we will create separate i18n chunk per js chunk,
12
+ with this we already load Js chunks are on demand and now we also download i18n also ondemand with this the initial and forthere actions.
13
+ when js download's we will download i18n with it.
14
+
15
+ ### How to we going to i18n split?
16
+ we will read the js chunk and collect I18n keys form it,
17
+ then we will create i18n chunk files with these used keys.
18
+
19
+ ### how do you collect i18n keys from js files?
20
+ we will traverse the js file's AST (static analysis) and find i18 keys,
21
+ we will concider all string which is in jsResource file as i18n keys.
22
+ and you can tell dynamic i18n key by js comments,
23
+ Like Below:-
24
+ ```js
25
+ fetch("tickets?view=view1").then(data => {
26
+ // I18n support.ticketsEmpty
27
+ // I18n support.viewNotFount
28
+ // I18n support.permissionDenied
29
+ let text = getI18nValue(data.i18nkey);
30
+ })
31
+ ```
32
+
33
+ ### is there any posiblity for unwanted keys in some chunk?
34
+ Yes, there is two posiblity
35
+ 1. js comment , if you write js comment but it is not needed then it will be add into i18n chunk
36
+ `To Resolve` we currently do not have perfect idea for this, But we can check this by chunk size limit.
37
+ `idea's will be welcome`
38
+ 2. like we said "we will concider all string which is in jsResource file as i18n keys",
39
+ So if you use string not for i18n but it was in jsResource then it will be add into i18n chunk.
40
+ `To Resolve` this problem we can use some kinda prefix or something.
41
+
42
+ ### how do we downlowd and give to app?
43
+ we have over write defualt webpack requireEnsure (every dynamic chunk requests are done by that function) function.
44
+ and we parlarly dowload i18n files. and we ask jsonFunction, to our plugin.
45
+ So we send i18nkeys , when it was download,
46
+ you must store all i18n keys, we give asycrnsly by that function download in that patticular.
47
+ so you must store and update (like append or assign) everytime that function call.
48
+
49
+ ### how to use this feature?
50
+ to use this feature use have give the below oprtions
51
+ `package.json`
52
+ ```json
53
+ {
54
+ /// ...some things
55
+ "react-cli": {
56
+ // ...some things
57
+ "i18n": {
58
+ "chunkSplitEnable": true,
59
+ "jsResource": "./deskapp/properties/JSResources.properties",
60
+ "localeVarName": "window.userInfo.langCode",
61
+ "jsonpFunc": "window.loadI18nChunk",
62
+ "templateLabel": "{{--user-locale}}",// this is for html template i18n file path locate template
63
+ "propertiesFolder": "./deskapp/properties"
64
+ },
65
+ // ...some things
66
+ }
67
+ }
68
+ ```
69
+
70
+
71
+ <!-- not need below -->
72
+ <!--
73
+
74
+ ### is there any problems with static analysis?
75
+ Yes,
76
+
77
+ ### how do we use dynamic i18n key?
78
+
79
+ and we will download i18n file with
80
+
81
+ and when js chunk download's then we will download i18n as need.
82
+ we all know in our app we loading i18n as one single big file for each locale(language).
83
+ we are going to split i18n as per js chunk, and when js chunk download's then we will download i18n as need.
84
+
85
+
86
+ -->
@@ -0,0 +1,25 @@
1
+ # I18n Split As Chunks Plugin
2
+
3
+ generaly we have manage our all I18n keys and values as language specific i18n files and then we download all i18n in initial page load.
4
+
5
+ Ok, what is the problem with this?.
6
+ the problem is i18n file keep get's grown it will affect the the inital page load and critial rendering path.
7
+ So, We have decide to create a plugin for split i18n per chunk's of js vise, Which mean we diside to create for each js chunk has its own i18n chunks, with this we already load Js chunks are on demand and now we also download i18n also ondemand with this the initial and forthere actions.
8
+
9
+ Ok, How to you do this thing?
10
+ we have read the js chunk and collect I18n keys what are used in that chunk and we will create i18n chunk files with only used key.
11
+
12
+ Ok, How do you collect that keys?
13
+ we now have two expremental statrge to collect I18n keys.
14
+
15
+ 1. we read jsResource.properties (or all keys I18n file) then we walk this AST of js and we collect all string which is jsResource.properties.
16
+ 2. for dynamic we discide to use comment some thing like
17
+ `// I18n support.tickekt.email.notvalid`
18
+
19
+ ok, how do you downlowd and give to app?
20
+ we have over write defualt webpack require ensure function.
21
+ So every dynamic chunk requset are done by that function.
22
+ So we parlarly dowload i18n files. and we ask jsonFunction, to our plugin.
23
+ So we send i18nkeys , when it was download,
24
+ you must store all i18n keys, we give asycrnsly by that function download in that patticular.
25
+ so you must store and update (like append or assign) everytime that function call.
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _utils = require("./utils");
9
+
10
+ var _webpack = require("webpack");
11
+
12
+ var _I18nKeysIdentifer = _interopRequireDefault(require("./I18nKeysIdentifer"));
13
+
14
+ var _I18nFilesEmitter = _interopRequireDefault(require("./I18nFilesEmitter"));
15
+
16
+ var _I18nDownlodLogic = _interopRequireDefault(require("./I18nDownlodLogic"));
17
+
18
+ var _getI18nKeysFormModules = _interopRequireDefault(require("./utils/getI18nKeysFormModules"));
19
+
20
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
+
22
+ // #region initial
23
+
24
+ /**
25
+ * @TODO:
26
+ * [?] add comment line options for properties file and get all keys form property file do right way to genarate them
27
+ * [?] need to discuss with collectI18n Keys with js comment need to conform "what is the comment? "
28
+ */
29
+
30
+ /**
31
+ * Notes: this plugin has done below works
32
+ * 1. collect I18n Keys from js files and make it as Depenencies
33
+ * 2. we create file(asset) for chunk specific i18nChunk Files
34
+ * 3. create hash for the specific i18nChunk Files
35
+ * 4. write logic to requireEnsure method for dowlod I18n chunk download dynamicaly
36
+ * 5. create manifest.json file which has the mapping of chunk-locales-i18nChunkFile
37
+ * for the external referrece.
38
+ * Hints :-
39
+ * - file means your machine files
40
+ * - asset means that also file but that will create by webpack after build
41
+ */
42
+ // const getI18nLocales = require('./utils/getI18nLocales');
43
+ // const { ConcatSource, SourceMapSource, OriginalSource } = sources;
44
+ const {
45
+ createHash
46
+ } = _webpack.util;
47
+ const MODULE_TYPE = 'json/i18n';
48
+
49
+ const i18ntype = locale => `${MODULE_TYPE}/${locale}`;
50
+
51
+ const pluginName = 'i18n-plugin';
52
+ /**
53
+ * @typedef I18nPluginOptions
54
+ * @property {String} filenameTemplate this was template for i18n chunk
55
+ * @property {String} jsResource this was path for jsResource i18n file
56
+ * @property {String} propertiesFolder this was path for propertiesFolder i18n file
57
+ * @property {Boolean} disableDefault this option for disable defulat value for i18n keys, means if the language file does not have some key we don't give jsResource value
58
+ * @property {String} i18nManifestFileName this was ouput path for i18n manifest.
59
+ * @property {String} jsonpFunc this was function name, we will call that function everytime i18n chunk download.
60
+ * @property {String} localeVarName this was variable name, we will call that function everytime i18n chunk download.
61
+ *
62
+ */
63
+
64
+ class I18nPlugin {
65
+ constructor(options = {}) {
66
+ // initialize options
67
+ this.options = Object.assign({
68
+ filenameTemplate: 'i18n/[locale]/[name].i18n.js'
69
+ }, options);
70
+ const {
71
+ filenameTemplate,
72
+ publicPath,
73
+ localeVarName,
74
+ i18nManifestFileName,
75
+ disableDefault,
76
+ jsResource,
77
+ propertiesFolder,
78
+ jsonpFunc
79
+ } = this.options;
80
+ this.publicPath = publicPath; // gethere i18n keys and values
81
+
82
+ this.jsResourceI18nKeys = jsResource ? (0, _utils.getPropertiesAsJSON)(jsResource) : {};
83
+ this.allI18nObject = (0, _utils.getAllI18n)({
84
+ folderPath: propertiesFolder,
85
+ disableDefault,
86
+ jsResourceI18nKeys: this.jsResourceI18nKeys
87
+ }); // initialize base data's and plugis
88
+
89
+ this.locales = Object.keys(this.allI18nObject);
90
+ this.i18nKeysIdentifer = new _I18nKeysIdentifer.default(this.jsResourceI18nKeys);
91
+ this.i18nFilesEmitter = new _I18nFilesEmitter.default({
92
+ allI18nObject: this.allI18nObject,
93
+ locales: this.locales,
94
+ i18nManifestFileName,
95
+ filenameTemplate,
96
+ jsonpFunc
97
+ });
98
+ this.i18nDownlodLogic = new _I18nDownlodLogic.default({
99
+ filenameTemplate,
100
+ publicPath,
101
+ locales: this.locales,
102
+ localeVarName
103
+ });
104
+ }
105
+
106
+ maintainHashForAllI18nAssets(compilation) {
107
+ /**
108
+ * we write chunkHash logic inside of our plugin Because we only add Dependency not Module.
109
+ * So we need to update chunkHash for our assets
110
+ * and we not able tell with just Modules.
111
+ * Because, if we add Module for the Depenentcy then that module must has some hash.
112
+ * But our I18n Hash is no module specific it was chunk specific,
113
+ * that's why we do the stuf in the chunkHash hook.
114
+ */
115
+ compilation.hooks.chunkHash.tap(pluginName, (chunk, chunkHash) => {
116
+ const {
117
+ outputOptions
118
+ } = compilation;
119
+ const {
120
+ hashFunction,
121
+ hashDigest,
122
+ hashDigestLength
123
+ } = outputOptions;
124
+ const i18nKeys = (0, _getI18nKeysFormModules.default)(chunk.modulesIterable);
125
+
126
+ if (!i18nKeys.length) {
127
+ return;
128
+ }
129
+
130
+ const {
131
+ contentHash
132
+ } = chunk; // contentHash = {
133
+ // javascript: 'abcd2938',
134
+ // 'css/mini-extract': 'askdijasod'
135
+ // };
136
+
137
+ this.locales.forEach(locale => {
138
+ const contentHashStr = createHash(hashFunction).update(this.i18nFilesEmitter.getTemplateString(i18nKeys, locale)).digest(hashDigest);
139
+ contentHash[i18ntype(locale)] = contentHashStr.substring(0, hashDigestLength);
140
+ chunkHash.update(contentHashStr);
141
+ });
142
+ });
143
+ }
144
+
145
+ apply(compiler) {
146
+ this.i18nKeysIdentifer.apply(compiler);
147
+ compiler.hooks.thisCompilation.tap(pluginName, compilation => {
148
+ // this below hook was tapped for hash for the specific i18nChunk Files and write logic to requireEnsure
149
+ this.maintainHashForAllI18nAssets(compilation); // const { mainTemplate } = compilation;
150
+ // this.addDownloadLogicOfI18nInMainTemplate(mainTemplate);
151
+ });
152
+ this.i18nFilesEmitter.apply(compiler);
153
+ this.i18nDownlodLogic.apply(compiler);
154
+ }
155
+
156
+ }
157
+ /*
158
+ // TODO: need to reimplement this logic
159
+ // NOTE: this logic for split all content hash per mani chunk
160
+ // like add chunk content hash to main locale i18n file
161
+
162
+ // let isEntry = chunk.name === this.options.mainChunkName;
163
+ // if (chunk.name === 'main' && chunk.hasEntryModule()) {
164
+ if (isEntry) {
165
+ const hashSource = new ConcatSource();
166
+ const dummyChunk = new chunk.constructor();
167
+ hashSource.add('// it wil be I18N file hash');
168
+ const templateHooks = compilation.chunkTemplate.hooks;
169
+ let c = templateHooks.render.call(
170
+ templateHooks.module.call(
171
+ hashSource,
172
+ dummyChunk,
173
+ compilation.moduleTemplate.javascript,
174
+ compilation.dependencyTemplates
175
+ ),
176
+ dummyChunk,
177
+ compilation.moduleTemplate.javascript,
178
+ compilation.dependencyTemplates
179
+ );
180
+ console.log('entry, ', c, hashSource.toString());
181
+ }
182
+ */
183
+
184
+
185
+ exports.default = I18nPlugin;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.collectI18nKeysfromAST = collectI18nKeysfromAST;
7
+ exports.collectI18nKeysfromComments = collectI18nKeysfromComments;
8
+
9
+ const {
10
+ walk
11
+ } = require('estree-walker');
12
+
13
+ function collectI18nKeysfromAST(ast, allI18n) {
14
+ let i18nKeys = {};
15
+ walk(ast, {
16
+ enter: function (node) {
17
+ if (node.type === 'Literal') {
18
+ if ((node.raw[0] === '\'' || node.raw[0] === '"') && Object.hasOwnProperty.call(allI18n, node.value)) {
19
+ i18nKeys[node.value] = allI18n[node.value];
20
+ }
21
+ }
22
+ }
23
+ });
24
+ return Object.keys(i18nKeys);
25
+ }
26
+
27
+ const prefixI18nComment = 'I18N';
28
+ const prefixI18nComment1 = 'dynamic-i18n-key';
29
+
30
+ function getI18nKeysFromComment(comment) {
31
+ let commentString = comment.value.trim();
32
+ let i18nKeyStr;
33
+
34
+ if (commentString.startsWith(prefixI18nComment)) {
35
+ i18nKeyStr = commentString.slice(prefixI18nComment.length).trim();
36
+ } else if (commentString.startsWith(prefixI18nComment1)) {
37
+ i18nKeyStr = commentString.slice(prefixI18nComment1.length).trim();
38
+ }
39
+
40
+ if (!i18nKeyStr) {
41
+ return [];
42
+ }
43
+
44
+ const i18nKeys = i18nKeyStr.split(',');
45
+ return i18nKeys;
46
+ } // export function fromComments(comments, allI18n) {
47
+
48
+
49
+ function collectI18nKeysfromComments(comments, allI18n) {
50
+ // TODO: need to implement
51
+ let i18nKeys = {};
52
+
53
+ for (let comment of comments) {
54
+ let keys = getI18nKeysFromComment(comment);
55
+
56
+ for (let key of keys) {
57
+ if (key && allI18n[key]) {
58
+ i18nKeys[key] = allI18n[key];
59
+ }
60
+ }
61
+ }
62
+
63
+ return Object.keys(i18nKeys);
64
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getI18nFileUrlPathTemplate = getI18nFileUrlPathTemplate;
7
+
8
+ function getI18nFileUrlPathTemplate(compilation, chunk, filenameTemplate, localeTemplate) {
9
+ let urlpath = compilation.getPath(filenameTemplate, {
10
+ chunk
11
+ });
12
+ return urlpath.replace('[locale]', localeTemplate);
13
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = getI18nKeysFormModules;
7
+
8
+ var _I18nDependency = require("../I18nDependency");
9
+
10
+ function getI18nKeysFormModules(modules) {
11
+ const i18nTemObj = {};
12
+
13
+ for (let m of modules) {
14
+ for (let dep of m.dependencies) {
15
+ if (!(dep instanceof _I18nDependency.I18nDependency)) {
16
+ continue;
17
+ }
18
+
19
+ for (const key of dep.i18nKeys) {
20
+ i18nTemObj[key] = 1;
21
+ }
22
+ }
23
+ }
24
+
25
+ return Object.keys(i18nTemObj);
26
+ }