Skip to content

Commit

Permalink
fix: Warn to delete component CSS with theme generated in one run
Browse files Browse the repository at this point in the history
Related-to: #9948
  • Loading branch information
mshabarov committed Apr 22, 2021
1 parent 9c644b0 commit 51fb53a
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
],
"repository": "vaadin/flow",
"name": "@vaadin/theme-live-reload-plugin",
"version": "2.0.0",
"version": "3.0.0",
"main": "theme-live-reload-plugin.js",
"author": "Vaadin Ltd",
"license": "Apache-2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@ class ThemeLiveReloadPlugin {

/**
* Create a new instance of ThemeLiveReloadPlugin
* @param themeName current theme name
* @param processThemeResourcesCallback callback which is called on
* adding/deleting of theme resource files to re-generate theme meta
* data and apply theme changes to application.
*/
constructor(processThemeResourcesCallback) {
constructor(themeName, processThemeResourcesCallback) {
if (!themeName) {
throw new Error("Missing theme name");
}
this.themeName = themeName;
if (!processThemeResourcesCallback || typeof processThemeResourcesCallback !== 'function') {
throw new Error("Couldn't instantiate a ThemeLiveReloadPlugin" +
" instance, because theme resources process callback is not set" +
Expand All @@ -35,6 +40,9 @@ class ThemeLiveReloadPlugin {
" callback as a ThemeLiveReloadPlugin constructor parameter.");
}
this.processThemeResourcesCallback = processThemeResourcesCallback;
this.componentStyleFileRegexp = new RegExp('(\\\\|\/)themes(\\\\|\/)' +
this.getEscapedThemeName() + '(\\\\|\/)components(\\\\|\/)(.*)\\.css$');
this.themeGeneratedFileRegexp = /theme-[\s\S]*?\.generated\.js$/;
}

apply(compiler) {
Expand All @@ -44,28 +52,51 @@ class ThemeLiveReloadPlugin {
const changedFilesMap = compiler.watchFileSystem.watcher.mtimes;
if (changedFilesMap !== {}) {
let themeGeneratedFileChanged = false;
let themeGeneratedFileDeleted = false;
let componentStyleFileDeleted = false;
const changedFilesPaths = Object.keys(changedFilesMap);
logger.debug("Detected changes in the following files " + changedFilesPaths);
changedFilesPaths.map(file => `${file}`).forEach(file => {
// Webpack watches to the changes in theme-[my-theme].generated.js
// because it is referenced from theme.js. Changes in this file
// should not trigger the theme handling callback (which
// re-generates theme-[my-theme].generated.js),
// otherwise it will get into infinite re-compilation loop.
// There might be several theme generated files in the
// generated folder, so the condition does not contain the exact
// theme name
if (file.match(/theme-[\s\S]*?\.generated\.js$/)) {
themeGeneratedFileChanged = true;
}
});
if (!themeGeneratedFileChanged) {
changedFilesPaths.forEach(changedFilePath => {
const file = `${changedFilePath}`;
// Webpack watches to the changes in theme-[my-theme].generated.js
// because it is referenced from theme.js. Changes in this file
// should not trigger the theme handling callback (which
// re-generates theme-[my-theme].generated.js),
// otherwise it will get into infinite re-compilation loop.
// There might be several theme generated files in the
// generated folder, so the condition does not contain the exact
// theme name
themeGeneratedFileChanged = file.match(this.themeGeneratedFileRegexp);
const timestamp = changedFilesMap[changedFilePath];
if (timestamp === null || timestamp < 0) {
themeGeneratedFileDeleted = themeGeneratedFileChanged;
componentStyleFileDeleted = file.match(this.componentStyleFileRegexp);
}
});
// This is considered as a workaround for
// https://github.com/vaadin/flow/issues/9948: delete component
// styles and theme generated file in one run to not have webpack
// compile error
if (componentStyleFileDeleted && !themeGeneratedFileDeleted) {
logger.warn("Custom theme component stylesheet file has been " +
"deleted, but it is still referenced in 'generated/theme-" + this.themeName + ".generated.js' file.\n" +
"This causes webpack compilation error.\n" +
"Please refresh your app page in the browser, or, if it doesn't help, please restart your app.\n" +
"In your further work, please delete 'generated/theme-" + this.themeName + ".generated.js' " +
"in one run (simultaneously) with component stylesheet file.");
}

if (themeGeneratedFileDeleted || !themeGeneratedFileChanged) {
this.processThemeResourcesCallback(logger);
}
}
callback();
});
}

getEscapedThemeName() {
return this.themeName.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&');
}
}

module.exports = ThemeLiveReloadPlugin;
2 changes: 1 addition & 1 deletion flow-server/src/main/resources/webpack.generated.js
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ module.exports = {
dirs: [path.resolve(__dirname, 'frontend', 'themes', themeName, 'components'),
path.resolve(__dirname, 'src', 'main', 'resources', 'META-INF', 'resources', 'themes', themeName, 'components'),
path.resolve(__dirname, 'src', 'main', 'resources', 'static', 'themes', themeName, 'components')]
}), new ThemeLiveReloadPlugin(processThemeResourcesCallback)] : []),
}), new ThemeLiveReloadPlugin(themeName, processThemeResourcesCallback)] : []),

new StatsPlugin({
devMode: devMode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class ComponentThemeLiveReloadIT extends ChromeBrowserTest {

private File componentsDir;
private File componentCSSFile;
private File themeGeneratedFile;

@Before
public void init() {
Expand All @@ -59,6 +60,9 @@ public void init() {

componentCSSFile = new File(new File(themeFolder, "components"),
"vaadin-text-field.css");

themeGeneratedFile = new File("frontend/generated/theme-app-theme" +
".generated.js");
}

@After
Expand All @@ -70,7 +74,7 @@ public void cleanUp() {
doActionAndWaitUntilLiveReloadComplete(() -> {
deleteComponentStyles();
deleteFile(componentsDir);
}, true);
});
}
}

Expand All @@ -94,9 +98,9 @@ public void webpackLiveReload_newComponentStylesCreatedAndDeleted_stylesUpdatedO
waitUntilComponentCustomStyle(OTHER_BORDER_RADIUS);

// Live reload upon file deletion
doActionAndWaitUntilLiveReloadComplete(this::deleteComponentStyles,
true);
doActionAndWaitUntilLiveReloadComplete(this::deleteComponentStyles);
waitUntilComponentInitialStyle();
checkLogsForErrors();
}

private void waitUntilComponentInitialStyle() {
Expand Down Expand Up @@ -142,6 +146,11 @@ private void createOrUpdateComponentCSSFile(String borderRadius) {
}

private void deleteComponentStyles() {
Assert.assertTrue("Expected theme generated file to be present",
themeGeneratedFile.exists());
// workaround for https://github.com/vaadin/flow/issues/9948
// delete theme generated with component styles in one run
deleteFile(themeGeneratedFile);
deleteFile(componentCSSFile);
}

Expand All @@ -153,14 +162,9 @@ private void deleteFile(File fileToDelete) {
}

private void doActionAndWaitUntilLiveReloadComplete(Runnable action) {
doActionAndWaitUntilLiveReloadComplete(action, false);
}

private void doActionAndWaitUntilLiveReloadComplete(Runnable action,
boolean deleted) {
final String initialAttachId = getAttachIdentifier();
action.run();
waitForLiveReload(initialAttachId, deleted);
waitForLiveReload(initialAttachId);
}

private String getAttachIdentifier() {
Expand Down Expand Up @@ -191,15 +195,7 @@ private void createDirectoryIfAbsent(File dir) {
}
}

private void waitForLiveReload(final String initialAttachId,
boolean deleted) {
if (deleted) {
// TODO: workaround for https://github.com/vaadin/flow/issues/9948.
// one more page update is needed when a first webpack
// re-compilation fails due to issue above.
getDriver().navigate().refresh();
getCommandExecutor().waitForVaadin();
}
private void waitForLiveReload(final String initialAttachId) {
waitUntilWithMessage(d -> {
try {
final String newViewId = getAttachIdentifier();
Expand Down

0 comments on commit 51fb53a

Please sign in to comment.