UNPKG

4.75 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const path_1 = require("path");
4const fs_1 = require("fs");
5const utils = require("../lib/utils");
6var messages;
7(function (messages) {
8 messages["compilationComplete"] = "Webpack compilation complete.";
9 messages["startWatching"] = "Webpack compilation complete. Watching for file changes.";
10 messages["changeDetected"] = "File change detected. Starting incremental webpack compilation...";
11})(messages = exports.messages || (exports.messages = {}));
12/**
13 * This little plugin will report the webpack state through the console.
14 * So the {N} CLI can get some idea when compilation completes.
15 */
16class WatchStateLoggerPlugin {
17 apply(compiler) {
18 const plugin = this;
19 compiler.hooks.watchRun.tapAsync("WatchStateLoggerPlugin", function (compiler, callback) {
20 plugin.isRunningWatching = true;
21 if (plugin.isRunningWatching) {
22 console.log(messages.changeDetected);
23 }
24 process.send && process.send(messages.changeDetected, error => null);
25 callback();
26 });
27 compiler.hooks.afterEmit.tapAsync("WatchStateLoggerPlugin", function (compilation, callback) {
28 callback();
29 if (plugin.isRunningWatching) {
30 console.log(messages.startWatching);
31 }
32 else {
33 console.log(messages.compilationComplete);
34 }
35 let emittedFiles = Object
36 .keys(compilation.assets)
37 .filter(assetKey => compilation.assets[assetKey].emitted);
38 if (compilation.errors.length > 0) {
39 WatchStateLoggerPlugin.rewriteHotUpdateChunk(compiler, compilation, emittedFiles);
40 }
41 // provide fake paths to the {N} CLI - relative to the 'app' folder
42 // in order to trigger the livesync process
43 const emittedFilesFakePaths = emittedFiles
44 .map(file => path_1.join(compiler.context, file));
45 process.send && process.send(messages.compilationComplete, error => null);
46 // Send emitted files so they can be LiveSynced if need be
47 process.send && process.send({ emittedFiles: emittedFilesFakePaths }, error => null);
48 });
49 }
50 /**
51 * Rewrite an errored chunk to make the hot module replace successful.
52 * @param compiler the webpack compiler
53 * @param emittedFiles the emitted files from the current compilation
54 */
55 static rewriteHotUpdateChunk(compiler, compilation, emittedFiles) {
56 const chunk = this.findHotUpdateChunk(emittedFiles);
57 if (!chunk) {
58 return;
59 }
60 const { name } = utils.parseHotUpdateChunkName(chunk);
61 if (!name) {
62 return;
63 }
64 const absolutePath = path_1.join(compiler.outputPath, chunk);
65 const newContent = this.getWebpackHotUpdateReplacementContent(compilation.errors, absolutePath, name);
66 fs_1.writeFileSync(absolutePath, newContent);
67 }
68 static findHotUpdateChunk(emittedFiles) {
69 return emittedFiles.find(file => file.endsWith("hot-update.js"));
70 }
71 /**
72 * Gets only the modules object after 'webpackHotUpdate("bundle",' in the chunk
73 */
74 static getModulesObjectFromChunk(chunkPath) {
75 let content = fs_1.readFileSync(chunkPath, "utf8");
76 const startIndex = content.indexOf(",") + 1;
77 let endIndex = content.length - 1;
78 if (content.endsWith(';')) {
79 endIndex--;
80 }
81 return content.substring(startIndex, endIndex);
82 }
83 /**
84 * Gets the webpackHotUpdate call with updated modules not to include the ones with errors
85 */
86 static getWebpackHotUpdateReplacementContent(compilationErrors, filePath, moduleName) {
87 const errorModuleIds = compilationErrors.filter(x => x.module).map(x => x.module.id);
88 if (!errorModuleIds || errorModuleIds.length == 0) {
89 // could not determine error modiles so discard everything
90 return `webpackHotUpdate('${moduleName}', {});`;
91 }
92 const updatedModules = this.getModulesObjectFromChunk(filePath);
93 // we need to filter the modules with a function in the file as it is a relaxed JSON not valid to be parsed and manipulated
94 return `const filter = function(updatedModules, modules) {
95 modules.forEach(moduleId => delete updatedModules[moduleId]);
96 return updatedModules;
97 }
98 webpackHotUpdate('${moduleName}', filter(${updatedModules}, ${JSON.stringify(errorModuleIds)}));`;
99 }
100}
101exports.WatchStateLoggerPlugin = WatchStateLoggerPlugin;
102//# sourceMappingURL=WatchStateLoggerPlugin.js.map
\No newline at end of file