codymikol / karma-webpack

Karma webpack Middleware
MIT License
830 stars 221 forks source link

karma-webpack 5 fails to read files with a query parameter (e.g. font-awesome) #517

Closed rhuitl closed 10 months ago

rhuitl commented 2 years ago

Expected Behavior

As with earlier karma-webpack versions, a CSS referencing a file with a cache breaker (?v=4.7.0) should work.

Actual Behavior

Error: ENOENT: no such file or directory, open
  '/var/folders/s8/x7zt810n7458m_tpwt8ky5qr0000gp/T/_karma_webpack_358674/c1e38fd9e0e74ba58f7a.svg?v=4.7.0'

How Do We Reproduce?

mkdir bug && cd bug
npm init -y && npm i -D webpack karma karma-webpack karma-mocha mocha style-loader css-loader && npm i font-awesome
echo 'import "font-awesome/css/font-awesome.css"' > test.js

Use this text as karma.conf.js

const path = require("path");
const os = require("os");

const defaultWebpackOptions = {
  mode: 'development',
  output: {
    filename: '[name].js',
    path: path.join(os.tmpdir(), '_karma_webpack_') + Math.floor(Math.random() * 1000000),
  },
  watch: false,
  optimization: {
    runtimeChunk: 'single',
    splitChunks: {
      chunks: 'all',
      minSize: 0,
      cacheGroups: {
        commons: {
          name: 'commons',
          chunks: 'initial',
          minChunks: 1,
        },
      },
    },
  },
  module: {
    rules: [{
      test: /\.css$/,
      use: [
        "style-loader",
        {loader: "css-loader", options: {sourceMap: true}},
      ]
    }, {
      test: /\.(woff2?|eot|ttf|svg)$/,
      type: "asset/resource"
    }]
  }
};

module.exports = (config) => {
  config.set({
    frameworks: ['mocha', 'webpack'],
    plugins: ['karma-webpack', 'karma-mocha'],
    files: [{ pattern: 'test.js', watched: false }],
    preprocessors: {'test.js': ['webpack']},
    webpack: defaultWebpackOptions
  });
}
npx karma start

Output:

karma-webpack does not currently support customized filenames via
webpack output.filename, if this is something you need consider opening an issue.
defaulting [name].js to [name].js.
Webpack bundling...
assets by status 162 KiB [cached] 1 asset
assets by info 929 KiB [immutable]
  asset c1e38fd9e0e74ba58f7a.svg?v=4.7.0 434 KiB [emitted] [immutable] [from: node_modules/font-awesome/fonts/fontawesome-webfont.svg?v=4.7.0] (auxiliary name: commons) (auxiliary id hint: commons)
  asset 8b43027f47b20503057d.eot 162 KiB [emitted] [immutable] [from: node_modules/font-awesome/fonts/fontawesome-webfont.eot] (auxiliary name: commons) (auxiliary id hint: commons)
  asset 1e59d2330b4c6deb84b3.ttf?v=4.7.0 162 KiB [emitted] [immutable] [from: node_modules/font-awesome/fonts/fontawesome-webfont.ttf?v=4.7.0] (auxiliary name: commons) (auxiliary id hint: commons)
  asset f691f37e57f04c152e23.woff?v=4.7.0 95.7 KiB [emitted] [immutable] [from: node_modules/font-awesome/fonts/fontawesome-webfont.woff?v=4.7.0] (auxiliary name: commons) (auxiliary id hint: commons)
  asset 20fd1704ea223900efa9.woff2?v=4.7.0 75.4 KiB [emitted] [immutable] [from: node_modules/font-awesome/fonts/fontawesome-webfont.woff2?v=4.7.0] (auxiliary name: commons) (auxiliary id hint: commons)
assets by path *.js 148 KiB
  asset commons.js 139 KiB [emitted] (name: commons) (id hint: commons)
  asset runtime.js 8.39 KiB [emitted] (name: runtime)
  asset test.372843621.js 992 bytes [emitted] (name: test.372843621)
Entrypoint test.372843621 148 KiB (1.06 MiB) = runtime.js 8.39 KiB commons.js 139 KiB test.372843621.js 992 bytes 6 auxiliary assets
webpack 5.61.0 compiled successfully in 501 ms
29 10 2021 17:37:57.523:ERROR [karma-server]: Error during file loading or preprocessing
TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined
    at Hash.update (internal/crypto/hash.js:84:11)
    at Object.sha1 (/private/tmp/karma2/node_modules/karma/lib/utils/crypto-utils.js:9:8)
    at runProcessors (/private/tmp/karma2/node_modules/karma/lib/preprocessor.js:70:26)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async FileList.preprocess [as _preprocess] (/private/tmp/karma2/node_modules/karma/lib/preprocessor.js:106:5)
    at async Promise.all (index 0)
    at async /private/tmp/karma2/node_modules/karma/lib/file-list.js:90:11
    at async Promise.all (index 4)
29 10 2021 17:37:57.552:INFO [karma-server]: Karma v6.3.6 server started at http://localhost:9877/
29 10 2021 17:37:57.552:ERROR [karma-server]: UnhandledRejection: Error: ENOENT: no such file or directory, open '/var/folders/s8/x7zt810n7458m_tpwt8ky5qr0000gp/T/_karma_webpack_848897/c1e38fd9e0e74ba58f7a.svg?v=4.7.0'
    at Object.openSync (fs.js:476:3)
    at Object.readFileSync (fs.js:377:35)
    at /private/tmp/karma2/node_modules/karma-webpack/lib/webpack/plugin.js:20:66
    at Array.forEach (<anonymous>)
    at /private/tmp/karma2/node_modules/karma-webpack/lib/webpack/plugin.js:16:29
    at Hook.eval [as callAsync] (eval at create (/private/tmp/karma2/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:1)
    at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (/private/tmp/karma2/node_modules/tapable/lib/Hook.js:18:14)
    at /private/tmp/karma2/node_modules/webpack/lib/Compiler.js:491:23
    at Compiler.emitRecords (/private/tmp/karma2/node_modules/webpack/lib/Compiler.js:883:39)
    at /private/tmp/karma2/node_modules/webpack/lib/Compiler.js:483:11
29 10 2021 17:37:57.552:ERROR [karma-server]: Error: ENOENT: no such file or directory, open '/var/folders/s8/x7zt810n7458m_tpwt8ky5qr0000gp/T/_karma_webpack_848897/c1e38fd9e0e74ba58f7a.svg?v=4.7.0'
    at Object.openSync (fs.js:476:3)
    at Object.readFileSync (fs.js:377:35)
    at /private/tmp/karma2/node_modules/karma-webpack/lib/webpack/plugin.js:20:66
    at Array.forEach (<anonymous>)
    at /private/tmp/karma2/node_modules/karma-webpack/lib/webpack/plugin.js:16:29
    at Hook.eval [as callAsync] (eval at create (/private/tmp/karma2/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:1)
    at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (/private/tmp/karma2/node_modules/tapable/lib/Hook.js:18:14)
    at /private/tmp/karma2/node_modules/webpack/lib/Compiler.js:491:23
    at Compiler.emitRecords (/private/tmp/karma2/node_modules/webpack/lib/Compiler.js:883:39)
    at /private/tmp/karma2/node_modules/webpack/lib/Compiler.js:483:11 {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: '/var/folders/s8/x7zt810n7458m_tpwt8ky5qr0000gp/T/_karma_webpack_848897/c1e38fd9e0e74ba58f7a.svg?v=4.7.0'
}
codymikol commented 2 years ago

Thanks for opening an issue, I'll try and take a look at this sometime this weekend

rhuitl commented 2 years ago

A temporary workaround for me is to modify plugin.js to remove anything including and after a question mark:

this.controller.bundlesContent[webpackFileObj.name] = fs.readFileSync(
  filePath.replace(/\?.*/, ""),
  'utf-8'
);
codymikol commented 2 years ago

I have unfortunately proven that files can be named in this way so introducing the proposed change would be breaking for users in that situation 😞

I think this is potentially an outside issue related to file-loader I'm actually encountering the same issue as you in another project.

It seems that this file is picked up from this line in the font-awesome project

@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');

It seems to me that as it is pulled in from a url, it should parse the file name as foo/fonts/fontawesome-webfont.eot without the query param. It looks like it is incorrectly loaded into webpack this way under asset.info

  info: {
    sourceFilename: '../node_modules/font-awesome/fonts/fontawesome-webfont.woff2?v=4.7.0',
    immutable: true,
    contenthash: '4a2487b5cc6987c4f1de',
    size: 82
  },
codymikol commented 2 years ago

It looks like in webpack 5 file-loader is deprecated, if you change your file-loader rule to something like this for your tests

            {
                test: /\.(jpg|png|gif|svg|woff|woff2|eot|ttf)$/,
                type: 'asset/inline',
            },

Does that solve this issue for you?

rhuitl commented 2 years ago

Hey @codymikol thanks for looking into this. I've switched my project from Karma over to Jest, so this issue is no longer relevant for me.

Nonetheless, if you look at my minimal example above, there is no file-loader being used. And I had converted everything in my project to use various asset loading strategies before I observed this issue.

doktordirk commented 2 years ago

uff. found a workaround. remove the default [query] for assets eg by

output.assetModuleFilename = '[name][ext]',

or setting generator.filename for individual assets in the module.rules