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

Dev-server URL issues while migrating from Encore 0.33 to Encore 1.1, inside a virtual machine

Open Kocal opened this issue 3 years ago • 4 comments

Hi :wave:

I'm upgrading an application from Encore 0.33 to Encore 1.1 but I'm facing issues with the dev-server.

Encore 0.33

I'm running encore dev-server --hot --public https://localhost.symfony-app-template.fr:8080 --host 0.0.0.0 --disable-host-check, and this is my configuration:

const path = require('path');
const Encore = require('@symfony/webpack-encore');
const dotenv = require('dotenv');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

// Manually configure the runtime environment if not already configured yet by the "encore" command.
// It's useful when you use tools that rely on webpack.config.js file.
if (!Encore.isRuntimeEnvironmentConfigured()) {
  Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}

Encore
  // directory where compiled assets will be stored
  .setOutputPath('public/build/')
  // public path used by the web server to access the output path
  .setPublicPath('/build')
  // only needed for CDN's or sub-directory deploy
  // .setManifestKeyPrefix('build/')

  .addAliases({
    '@app': path.resolve(__dirname, 'assets/app/'),
  })

  /*
   * ENTRY CONFIG
   *
   * Add 1 entry for each "page" of your app
   * (including one that's included on every page - e.g. "app")
   *
   * Each entry will result in one JavaScript file (e.g. app.js)
   * and one CSS file (e.g. app.css) if you JavaScript imports CSS.
   */
  .addEntry('app', './assets/app')
  .addEntry('email', './assets/email/foundation.scss')
  .addEntry('email-responsive', './assets/email/foundation.responsive.css')
  .addEntry('page.home', './assets/pages/home')

  // When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
  .splitEntryChunks()

  // will require an extra script tag for runtime.js
  // but, you probably want this, unless you're building a single-page app
  .enableSingleRuntimeChunk()

  /*
   * FEATURE CONFIG
   *
   * Enable & configure other features below. For a full
   * list of features, see:
   * https://symfony.com/doc/current/frontend.html#adding-more-features
   */
  .cleanupOutputBeforeBuild()
  .enableSourceMaps(!Encore.isProduction())
  // enables hashed filenames (e.g. app.abc123.css)
  .enableVersioning(Encore.isProduction())

  // enables Vue support
  .enableVueLoader((vueLoaderOptions) => {
    // Remove attributes `data-testid` and `:data-testid` when building for production.
    // Those attributes are used to make end-to-end tests easier to write and read.
    if (Encore.isProduction()) {
      vueLoaderOptions.compilerOptions = vueLoaderOptions.compilerOptions || {};
      vueLoaderOptions.compilerOptions.modules = vueLoaderOptions.compilerOptions.modules || [];
      vueLoaderOptions.compilerOptions.modules.push({
        preTransformNode(astEl) {
          ['data-testid', ':data-testid'].forEach((dAttr) => {
            if (astEl.attrsMap[dAttr]) {
              delete astEl.attrsMap[dAttr];
              astEl.attrsList = astEl.attrsList.filter((x) => x.name !== dAttr);
            }
          });

          return astEl;
        },
      });
    }
  })

  // enables Sass/SCSS support
  .enableSassLoader()

  // enables PostCSS support
  .enablePostCssLoader()

  // enable TypeScript support
  .enableBabelTypeScriptPreset()

  // uncomment to get integrity="..." attributes on your script & link tags
  // requires WebpackEncoreBundle 1.4 or higher
  // .enableIntegrityHashes()

  // uncomment if you're having problems with a jQuery plugin
  // .autoProvidejQuery()

  .configureWatchOptions((watchOptions) => {
    watchOptions.poll = 250;
  })

  // Configure environment variables to inject into assets
  // Global env vars from `process.env` take priority over env vars from `.env` file.
  .configureDefinePlugin((options) => {
    const env = dotenv.config();
    if (env.error) {
      throw env.error;
    }

    ['SENTRY_DSN'].forEach((envVar) => {
      options['process.env'][envVar] = JSON.stringify(process.env[envVar] || env.parsed[envVar]);
    });
  })

  .configureDevServerOptions((options) => {
    options.https = {
      ...options.https,
      key: path.join(__dirname, 'var/localhost.symfony-app-template.fr+1-key.pem'),
      cert: path.join(__dirname, 'var/localhost.symfony-app-template.fr+1.pem'),
    };
  });

// When passing args --analyze
if (process.argv.includes('--analyze')) {
  Encore.addPlugin(new BundleAnalyzerPlugin({ analyzerHost: '0.0.0.0' }));
}

module.exports = Encore.getWebpackConfig();

Everything works fine:

  • assets are built correctly
  • dev-server is listening to 0.0.0.0 and allows external access (thanks to --disable-host-check)
  • the public URL is https://localhost.symfony-app-template.fr:8080(thanks to --public)

Encore 1.1

I removed --hot from the command and I'm now using encore dev-server --public https://localhost.symfony-app-template.fr:8080 --host 0.0.0.0.

This is my configuration:

diff --git a/webpack.config.js b/webpack.config.js
index bfc4558..412c9b3 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -53,6 +53,7 @@ Encore
   .enableSourceMaps(!Encore.isProduction())
   // enables hashed filenames (e.g. app.abc123.css)
   .enableVersioning(Encore.isProduction())
+  .disableCssExtraction(Encore.isDevServer())
 
   // enables Vue support
   .enableVueLoader((vueLoaderOptions) => {
@@ -110,6 +111,7 @@ Encore
   })
 
   .configureDevServerOptions((options) => {
+    options.firewall = false;
     options.https = {
       ...options.https,
       key: path.join(__dirname, 'var/localhost.symfony-app-template.fr+1-key.pem'),

But now I have the following errors in Chrome console: image

It looks like that --host is used to build URLs for the dev-server, so let's try something else!

I tried --host localhost.symfony-app-template.fr but now all assets are inacessible: image

Here is the manifest.json if it can help:

{
  "build/app.js": "https://localhost.symfony-app-template.fr:8080/build/app.js",
  "build/email.js": "https://localhost.symfony-app-template.fr:8080/build/email.js",
  "build/email-responsive.js": "https://localhost.symfony-app-template.fr:8080/build/email-responsive.js",
  "build/page.home.js": "https://localhost.symfony-app-template.fr:8080/build/page.home.js",
  "build/runtime.js": "https://localhost.symfony-app-template.fr:8080/build/runtime.js",
  "build/vendors-node_modules_webpack-dev-server_client_default_index_js_https_localhost_symfony-app-t-a2dca0.js": "https://localhost.symfony-app-template.fr:8080/build/vendors-node_modules_webpack-dev-server_client_default_index_js_https_localhost_symfony-app-t-a2dca0.js",
  "build/vendors-node_modules_css-loader_dist_runtime_api_js-node_modules_css-loader_dist_runtime_cssW-926fd9.js": "https://localhost.symfony-app-template.fr:8080/build/vendors-node_modules_css-loader_dist_runtime_api_js-node_modules_css-loader_dist_runtime_cssW-926fd9.js",
  "build/vendors-node_modules_babel_runtime_helpers_esm_applyDecoratedDescriptor_js-node_modules_babel-8fd6be.js": "https://localhost.symfony-app-template.fr:8080/build/vendors-node_modules_babel_runtime_helpers_esm_applyDecoratedDescriptor_js-node_modules_babel-8fd6be.js"
}

A solution

I tried many things and came to a solution that works:

  • remove --host from my command, which is now encore dev-server --public https://localhost.symfony-app-template.fr:8080
  • update Encore ConfigGenerator.buildDevServerConfig() like this: image

And after restarting Encore, everything works fine. Assets are found and dev-server/HMR are working properly: image

I think --host is interfering with something else but I don't know why. Argument --host is only used by Encore when creating the runtime config:

    switch (runtimeConfig.command) {
        // ...
        case 'dev-server':
            runtimeConfig.isValidCommand = true;
            runtimeConfig.environment = 'dev';
            runtimeConfig.verbose = true;

            runtimeConfig.useDevServer = true;
            runtimeConfig.devServerHttps = argv.https;
            runtimeConfig.devServerKeepPublicPath = argv.keepPublicPath || false;

            if (typeof argv.public === 'string') {
                runtimeConfig.devServerPublic = argv.public;
            }

            runtimeConfig.devServerHost = argv.host ? argv.host : 'localhost';
            runtimeConfig.devServerPort = argv.port ? argv.port : '8080';

            break;
    }

Maybe argument --host is also passed to webpack/webpack-cli/dev-server and interferes with Encore configuration? WDYT?

Thanks!

EDIT: I think that's the problem! When removing --host and updating lib/config/parse-runtime.js:51 to the following code, everything is working:

runtimeConfig.devServerHost = 'localhost.symfony-app-template.fr';

EDIT 2: well, in fact you can configure this yourself with Encore.configureDevServerOptions() like this:

Encore 
 .configureDevServerOptions((options) => {
    // ...
    options.client.host = 'localhost.symfony-app-template.fr';
  });

So I guess that's not really an issue... or at least that will help people facing the same problem than me. :shrug:

Kocal avatar Mar 16 '21 12:03 Kocal

Hi, thanks for sharing your issue and your solution. I just found your issue after posting mine. https://github.com/symfony/webpack-encore/issues/948 They are similar in a way.

I tried to follow your recommendations and combine your settings with my integration but it seems the solution is somewhere else for me.

cedricgeffroy avatar Mar 16 '21 17:03 cedricgeffroy

Possibly related:

  • https://github.com/symfony/webpack-encore/pull/939
  • https://github.com/symfony/webpack-encore/issues/931

leevigraham avatar Mar 19 '21 00:03 leevigraham

And also related I guess: #947

Kocal avatar Mar 19 '21 07:03 Kocal

I have the same problem after upgrading from v0.33 to v1.2.

Everything is working fine, except for the live-reload/HMR of the dev-server.

In the browsers console I get:

Firefox kann keine Verbindung zu dem Server unter wss://localhost:8090/ws aufbauen.

I'm running encore inside a docker container and use the local URL https://my-site.local via /etc/hosts entry: 127.0.0.1 my-site.local

The docker container starts the webpack-dev-server via command inside my docker-compose.yml: command: ["npm", "run", "dev-server"]

Which is the NPM script: "dev-server": "encore dev-server --public https://my-site.local:8090"

In encore the dev-server is configured as follows:

Encore
    .configureDevServerOptions(options => {
        options.firewall = false;
        options.host = '0.0.0.0';
        options.port = 8090;
        options.https = {
            key: '/var/ssl/server.key',
            cert: '/var/ssl/server.crt',
        };
    })

The solution from above works for me, too. When I change the config like this, the browser can connect again:

Encore
    .configureDevServerOptions(options => {
+       options.client.host = 'my-site.local';
        options.firewall = false;
        options.host = '0.0.0.0';
        options.port = 8090;
        options.https = {
            key: '/var/ssl/server.key',
            cert: '/var/ssl/server.crt',
        };
    })

It seems that client.host was set via --public somehow, but #939 changed this by setting it explicitly to another value.

jdreesen avatar May 04 '21 16:05 jdreesen