webpack-encore icon indicating copy to clipboard operation
webpack-encore copied to clipboard

Upgrading to Encore 1.1 slows down build

Open bobvandevijver opened this issue 3 years ago • 5 comments

I'm not sure whether this is related to anything in the upgrade of Encore, Webpack or any related dependency, but I'm curious if any of you might know what might be causing this.

This was my original webpack.config.js

const path = require('path');
const fs = require('fs');
const Encore = require('@symfony/webpack-encore');
const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

if (!Encore.isRuntimeEnvironmentConfigured()) {
  Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}

Encore
    .setOutputPath('public/build/')
    .setPublicPath('/build')

    // Default layout
    .addEntry('layout', './assets/js/layout.ts')
    // Default application code
    .addEntry('app', './assets/js/app.ts')
    // Vue page entry point
    .addEntry('vue_page', './assets/js/pages/vue_page.ts')
    // Vue notification entry point
    .addEntry('vue_notifications', './assets/js/notifications/notifications.ts')
    // Vue elevation entry point
    .addEntry('vue_elevation', './assets/js/elevation/elevation.ts')
    // Vue elevation entry point
    .addEntry('vue_system_notifications', './assets/js/system_notifications/system_notifications.ts')

    // Enable Vue loader
    .enableVueLoader(() => {
    }, {runtimeCompilerBuild: false})

    // Do not load images as ES module
    .configureUrlLoader({
      images: {
        esModule: false,
      },
    })

    // Copy and version all image assets
    .copyFiles({
      from: './assets/img',
      to: 'img/[path][name].[hash:8].[ext]',

      // only copy files matching this pattern
      pattern: /\.(png|jpg|jpeg|svg)$/,
    })

    .splitEntryChunks()
    .enableSingleRuntimeChunk()
    .cleanupOutputBeforeBuild()
    .enableSourceMaps()
    .enableVersioning(Encore.isProduction())

    // Polyfill and transpilation options
    .configureBabel(null, {
      includeNodeModules: ['@drenso/vue-frontend-shared'],
    })

    .enableSassLoader()
    .enableBabelTypeScriptPreset()
    .enablePostCssLoader()
    .enableIntegrityHashes(Encore.isProduction())
    .autoProvidejQuery()
    .autoProvideVariables({
      Popper: ['popper.js', 'default'],
    })

    .addLoader({
      test: /\b(frontend|messages|validators|drenso_shared)\+intl-icu\.(.+)\.yml$/,
      loader: 'messageformat-loader',
      type: 'javascript/auto',
    })

    .addPlugin(new MomentLocalesPlugin())
    .addPlugin(new ForkTsCheckerWebpackPlugin({
      typescript: {
        extensions: {
          vue: true,
        },
      },
    }))

    .configureDevServerOptions(options => {
      options.disableHostCheck = true;
    })

    // Fixes CSS HMR
    // See https://github.com/symfony/webpack-encore/issues/348
    .disableCssExtraction(Encore.isDevServer())
;

const webpackConfig = Encore.getWebpackConfig();

// Add aliases
webpackConfig.resolve.alias['@'] = path.resolve(__dirname, 'assets/js');
webpackConfig.resolve.alias['@fos'] = path.resolve(__dirname, 'vendor/friendsofsymfony/jsrouting-bundle/Resources/public/js');
webpackConfig.resolve.alias['@trans'] = path.resolve(__dirname, 'translations');
webpackConfig.resolve.alias['@drensoTrans'] = path.resolve(__dirname, 'vendor/drenso/symfony-shared/src/Resources/translations');

module.exports = webpackConfig;

I made the following changes for the upgrade:

diff --git a/package.json b/package.json
index 75acf6e9..aa91c2b5 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
         "@babel/plugin-proposal-decorators": "^7.10.5",
         "@babel/plugin-proposal-logical-assignment-operators": "^7.12.13",
         "@babel/preset-env": "^7.10.4",
-        "@symfony/webpack-encore": "^0.33.0",
+        "@symfony/webpack-encore": "^1.1.2",
         "@types/big.js": "^6.0.2",
         "@types/bootstrap": "^4.6.0",
         "@types/color": "^3.0.1",
@@ -16,11 +16,12 @@
         "@types/uuid": "^8.3.0",
         "@types/vue-color": "^2.4.3",
         "@types/webpack-env": "^1.16.0",
-        "@vue/cli-plugin-typescript": "^4.5.11",
-        "@vue/cli-service": "^4.5.11",
+        "@vue/cli-plugin-typescript": "^5.0.0-alpha.5",
+        "@vue/cli-service": "^5.0.0-alpha.5",
         "autoprefixer": "^10.2.4",
         "babel-preset-typescript-vue": "^1.1.1",
         "core-js": "^3.9.0",
+        "file-loader": "^6.2.0",
         "fork-ts-checker-webpack-plugin": "^6.1.0",
         "messageformat-loader": "^0.8.1",
         "moment-locales-webpack-plugin": "^1.2.0",
@@ -36,12 +37,13 @@
         "url-loader": "^4.1.1",
         "vue-loader": "^15.9.6",
         "vue-template-compiler": "^2.6.12",
+        "webpack-dev-server": "^4.0.0-beta.0",
         "webpack-notifier": "^1.13.0"
     },
     "license": "UNLICENSED",
     "private": true,
     "scripts": {
-        "dev-server": "yarn build:email && yarn watch:email & encore dev-server --host localhost.drenso.dev --hot --https --cert /etc/apache2/ssl/drenso.dev/fullchain.pem --key /etc/apache2/ssl/drenso.dev/privkey.pem",
+        "dev-server": "yarn build:email && yarn watch:email & encore dev-server --host localhost.drenso.dev",
         "dev-server-bob": "yarn dev-server --port 8999",
         "dev-server-tobias": "yarn dev-server --port 8998",
         "dev": "yarn dev:email && yarn dev:encore",
@@ -92,6 +94,6 @@
         "vue-property-decorator": "^9.1.2"
     },
     "resolutions": {
-        "fork-ts-checker-webpack-plugin": "^6.1.0"
+        "vue-loader": "^15.9.6"
     }
 }
diff --git a/webpack.config.js b/webpack.config.js
index 9119e5b0..5c55b119 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,5 +1,4 @@
 const path = require('path');
-const fs = require('fs');
 const Encore = require('@symfony/webpack-encore');
 const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
 const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
@@ -49,11 +48,14 @@ Encore
     .enableVueLoader(() => {
     }, {runtimeCompilerBuild: false})

+    .configureMiniCssExtractPlugin(() => {
+    }, (pluginConfig) => {
+      pluginConfig.ignoreOrder = true;
+    })
+
     // Do not load images as ES module
-    .configureUrlLoader({
-      images: {
-        esModule: false,
-      },
+    .configureImageRule({
+      type: 'asset/resource',
     })

     // Copy and version all image assets
@@ -132,6 +134,22 @@ Encore
     // Fixes CSS HMR
     // See https://github.com/symfony/webpack-encore/issues/348
     .disableCssExtraction(Encore.isDevServer())
+
+    .configureDevServerOptions(options => {
+      options.firewall = false;
+      options.https = {
+        cert: '/etc/apache2/ssl/drenso.dev/fullchain.pem',
+        key: '/etc/apache2/ssl/drenso.dev/privkey.pem',
+      }
+    })
+
+    // Enable the webpack build cache
+    .enableBuildCache({
+          // object of "buildDependencies"
+          // https://webpack.js.org/configuration/other-options/#cachebuilddependencies
+          // __filename means that changes to webpack.config.js should invalidate the cache
+          config: [__filename],
+      });
 ;

 const webpackConfig = Encore.getWebpackConfig();

The initial build now takes about 5 seconds longer (but that's not what I worry about), but the HMR rebuild when running the dev server are about 80% slower. It was around 1 second on Encore 0.33, but now it is more around 1.8 seconds, which is already with the new build cache enabled.

Does anybody have a clue?

bobvandevijver avatar Mar 01 '21 08:03 bobvandevijver

I experienced something similar when attempting to upgrade (I had to revert to webpack-encore < v1 and webpack v4). I think this thread is related: https://github.com/webpack/webpack/issues/12102.

caseyjhol avatar Mar 01 '21 17:03 caseyjhol

That does indeed feels like as what I'm experiencing... I tried enabling the unsafeCache as suggested in the linked thread, and that does significantly improve the rebuild time: after a few rebuilds (probably due to other caching mechanisms?) it got back around 1.1 seconds, which is fine. But apparently, it is not recommended:

module graph validation takes about ~100ms extra in webpack 5

  • webpack 5 is using a safe cache. webpack 4 uses an unsafe cache
  • You can change that with module.unsafeCache: true, but I don't recommend that

Also, when looking at the documentation of the option, it seems like the default value should be the preferred one.

bobvandevijver avatar Mar 02 '21 08:03 bobvandevijver

@bobvandevijver how did you enable this inside Encore config ?

kl3sk avatar Mar 02 '21 13:03 kl3sk

@kl3sk Like this:

const webpackConfig = Encore.getWebpackConfig();

// Set unsafe cache
webpackConfig.module.unsafeCache = true;

module.exports = webpackConfig;

bobvandevijver avatar Mar 02 '21 14:03 bobvandevijver

Thanks I'll have a try.

Edit: after 2 days, I don"t see any increased perfs.

kl3sk avatar Mar 02 '21 14:03 kl3sk