linaria: ReferenceError: window is not defined when using react-refresh-webpack-plugin

Environment

  • Linaria version: 3-beta.17
  • Bundler (+ version): webpack 5.64
  • Node.js version: 16
  • OS: ubuntu 20.04 on wsl2 on win10
  • react-refresh-webpack-plugin: 0.5.4
  • react-error-overlay: 6.0.9
  • using thread-loader

Description

ERROR in ./src/App.tsx (./src/App.linaria.css!=!../../node_modules/@linaria/webpack5-loader/lib/outputCssLoader.js?cacheProvider=%2Fhome%2Fntucker%2Fsrc%2Fanansi%2Fpackages%2Fwebpack-config-anansi%2Flib%2Fbase%2FlinariaFileCache.js!./src/App.tsx)
Module build failed (from ../../node_modules/mini-css-extract-plugin/dist/loader.js):
HookWebpackError: window is not defined
    at tryRunOrWebpackError (/home/ntucker/src/anansi/node_modules/webpack/lib/HookWebpackError.js:88:9)
    at __webpack_require_module__ (/home/ntucker/src/anansi/node_modules/webpack/lib/Compilation.js:4979:12)
    at __webpack_require__ (/home/ntucker/src/anansi/node_modules/webpack/lib/Compilation.js:4936:18)
    at Object.<anonymous> (/home/ntucker/src/anansi/node_modules/thread-loader/dist/cjs.js!/home/ntucker/src/anansi/node_modules/babel-loader/lib/index.js??ruleSet[1].rules[0].oneOf[1].use[1]!/home/ntucker/src/anansi/node_modules/@linaria/webpack-loader/lib/index.js??ruleSet[1].rules[0].oneOf[1].use[2]!/home/ntucker/src/anansi/packages/webpack-config-anansi/lib/plugins/refreshOverlayModule.js:12:5)
    at /home/ntucker/src/anansi/node_modules/webpack/lib/javascript/JavascriptModulesPlugin.js:432:11
    at Hook.eval [as call] (eval at create (/home/ntucker/src/anansi/node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:7:1)
    at /home/ntucker/src/anansi/node_modules/webpack/lib/Compilation.js:4981:39
    at tryRunOrWebpackError (/home/ntucker/src/anansi/node_modules/webpack/lib/HookWebpackError.js:83:7)
    at __webpack_require_module__ (/home/ntucker/src/anansi/node_modules/webpack/lib/Compilation.js:4979:12)
    at __webpack_require__ (/home/ntucker/src/anansi/node_modules/webpack/lib/Compilation.js:4936:18)
-- inner error --
ReferenceError: window is not defined
    at Object.<anonymous> (/home/ntucker/src/anansi/node_modules/react-error-overlay/lib/index.js:2:44)
    at /home/ntucker/src/anansi/node_modules/webpack/lib/javascript/JavascriptModulesPlugin.js:432:11
    at Hook.eval [as call] (eval at create (/home/ntucker/src/anansi/node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:7:1)
    at /home/ntucker/src/anansi/node_modules/webpack/lib/Compilation.js:4981:39
    at tryRunOrWebpackError (/home/ntucker/src/anansi/node_modules/webpack/lib/HookWebpackError.js:83:7)
    at __webpack_require_module__ (/home/ntucker/src/anansi/node_modules/webpack/lib/Compilation.js:4979:12)
    at __webpack_require__ (/home/ntucker/src/anansi/node_modules/webpack/lib/Compilation.js:4936:18)
    at Object.<anonymous> (/home/ntucker/src/anansi/node_modules/thread-loader/dist/cjs.js!/home/ntucker/src/anansi/node_modules/babel-loader/lib/index.js??ruleSet[1].rules[0].oneOf[1].use[1]!/home/ntucker/src/anansi/node_modules/@linaria/webpack-loader/lib/index.js??ruleSet[1].rules[0].oneOf[1].use[2]!/home/ntucker/src/anansi/packages/webpack-config-anansi/lib/plugins/refreshOverlayModule.js:12:5)
    at /home/ntucker/src/anansi/node_modules/webpack/lib/javascript/JavascriptModulesPlugin.js:432:11
    at Hook.eval [as call] (eval at create (/home/ntucker/src/anansi/node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:7:1)

It seems that the react-refresh is being injected into CSS maybe? Previously my thread-loader guarded against processing linaria js files via:

{
              test: /\.(t|j)sx?$/,
              // TODO: Remove when we stop supporting linaria betas
              exclude: /\.linaria-cache/,
}

However, now the caching system has changed I don’t know how to avoid this.

Refresh configuration:

        new ReactRefreshWebpackPlugin({
          overlay: {
            // provides editor opening when combined with ErrorOverlayPlugin
            entry: require.resolve('./plugins/ErrorOverlayEntry'),
            // registers error handlers
            module: require.resolve('./plugins/refreshOverlayModule'),
            sockHost: config.devServer.client.webSocketURL.hostname,
            sockPath: config.devServer.client.webSocketURL.pathname,
            sockPort: config.devServer.client.webSocketURL.port,
          },
        }),

Note that removing the overlay makes this error go away. (as the react-error-overlay code in the trace above is no longer added to files)

Reproducible Demo

Here’s my cacheProvider:

const findCacheDir = require('find-cache-dir');
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const mkdirp = require('mkdirp');

const hashFileName = name => {
  const hash = crypto.createHash('md4');
  hash.update(name);
  return hash.digest('hex');
};

class LinariaFileCache {
  constructor() {
    const linariaCacheDir = findCacheDir({
      name: `.linaria-${process.env.NODE_ENV}`,
      cwd: process.cwd(),
    });
    if (!linariaCacheDir) {
      throw new Error('Get linaria cache dir failed');
    }
    mkdirp.sync(linariaCacheDir);
    this.linariaCacheDir = linariaCacheDir;
  }

  async get(key) {
    return fs.promises.readFile(
      path.join(this.linariaCacheDir, `${hashFileName(key)}.css`),
      'utf8',
    );
  }

  async set(key, value) {
    return fs.promises.writeFile(
      path.join(this.linariaCacheDir, `${hashFileName(key)}.css`),
      value,
      'utf8',
    );
  }
}

module.exports = new LinariaFileCache();

Full demo is:

  1. git clone git@github.com:ntucker/anansi.git
  2. git checkout de8516c222556e578786c6ae77778ce3019d9230
  3. yarn install from root
  4. cd examples/linaria
  5. yarn start

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 4
  • Comments: 15

Most upvoted comments

If I change the react refresh plugin to exclude processing outputCssLoader all works fine.

  if (
    !/outputCssLoader\.js/.test(moduleData.request) && 
    // Include and exclude user-specified files
    match(moduleData.matchResource || moduleData.resource) &&
    // Exclude files referenced as assets
    !moduleData.type.includes('asset') &&
    // Skip react-refresh and the plugin's runtime utils to prevent self-referencing -
    // this is useful when using the plugin as a direct dependency,
    // or when node_modules are specified to be processed.
    !moduleData.resource.includes(reactRefreshPath) &&
    !moduleData.resource.includes(refreshUtilsPath) &&
    // Check to prevent double injection
    !moduleData.loaders.find(({ loader }) => loader === resolvedLoader)
  ) {

https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/ac9dc02e4cfc6251e9790366df9d1fc61d810fcb/lib/utils/injectRefreshLoader.js#L28

On my tests moduleData.matchResource and moduleData.resource both refers to the original file not the “dynamic module” (I think it’s how this is called) that includes the outputCssLoader.js. So I had to test against moduleData.request instead.

UPDATE: submitted a PR: https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/726