threads-plugin icon indicating copy to clipboard operation
threads-plugin copied to clipboard

Use with Webpack 5 not working

Open alexpreynolds opened this issue 7 months ago • 0 comments

I am using webpack v5.89.0 and trying to transpile a modified version of the higlass-pileup project to use newer webpack and babel resources, so that it can be processed with current versions of Node.js.

I am using the workaround described here to get the worker script generated.

The error message I get is as follows:

% npm run build
npm run build

> [email protected] build
> npm run build-es && webpack --mode production


> [email protected] build-es
> rm -rf ./es/* && npx babel ./src/ --out-dir ./es/ --env-name esm

Successfully compiled 6 files with Babel (811ms).
/Users/areynolds/Developer/Test/higlass-pileup/webpack.config.js:23
          throw Error(
          ^

Error: Waited too long for the target file (dist/worker.js) to be generated. Exiting.
    at Timeout.poll [as _onTimeout] (/Users/areynolds/Developer/Test/higlass-pileup/webpack.config.js:23:17)
    at listOnTimeout (node:internal/timers:559:17)
    at processTimers (node:internal/timers:502:7)

Node.js v17.9.1

Increasing the timeout value for WaitPlugin does not appear to change this result (other than taking longer to get to the error message.

Here are my customized resource files, which I believe to be relevant to the problem:

package.json

{
  "name": "higlass-pileup",
  "version": "1.5.0",
  "description": "HiGlass Pileup Track",
  "keywords": [
    "HiGlass",
    "Track"
  ],
  "author": "Peter Kerpedjiev",
  "license": "MIT",
  "contributors": [
    {
      "name": "Peter Kerpedjiev",
      "url": "http://github.com/pkerpedjiev"
    }
  ],
  "repository": {
    "type": "git",
    "url": "git://github.com/higlass/higlass-pileup.git"
  },
  "main": "src/index.js",
  "unpkg": "dist/higlass-pileup.min.js",
  "module": "./es",
  "files": [
    "dist",
    "es"
  ],
  "devDependencies": {
    "@babel/cli": "^7.23.4",
    "@babel/core": "^7.23.3",
    "@babel/eslint-parser": "^7.23.3",
    "@babel/plugin-transform-object-rest-spread": "^7.23.4",
    "@babel/preset-env": "^7.23.3",
    "babel-loader": "^9.1.3",
    "before-build-webpack": "^0.2.11",
    "eslint": "^8.7.0",
    "eslint-config-airbnb": "^19.0.4",
    "eslint-plugin-import": "^2.14.0",
    "eslint-plugin-jsx-a11y": "^6.1.2",
    "eslint-plugin-react": "^7.14.2",
    "file-loader": "^6.2.0",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^5.5.3",
    "prettier": "^2.1.2",
    "style-loader": "^0.20.3",
    "terser-webpack-plugin": "^5.3.9",
    "threads-plugin": "^1.4.0",
    "webpack": "^5.89.0",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^4.15.1",
    "webpack-plugin-replace": "^1.2.0"
  },
  "scripts": {
    "build-es": "rm -rf ./es/* && npx babel ./src/ --out-dir ./es/ --env-name esm",
    "build": "npm run build-es && webpack --mode production",
    "start": "webpack serve --mode development -c webpack.config.js",
    "prerelease": "rm -rf dist/*; npm run build; zip -r dist.zip dist",
    "clean": "rm -rf node_modules && rm -f package-lock.json && rm -rf dist && rm -rf build"
  },
  "dependencies": {
    "@gmod/bam": "2.0.0",
    "d3-array": "^2.3.1",
    "d3-dsv": "^1.1.1",
    "d3-format": "^3.0.1",
    "d3-request": "^1.0.6",
    "d3-scale": "^3.0.1",
    "higlass-register": "^0.1.0",
    "lru-cache": "^6.0.0",
    "raw-loader": "^4.0.2",
    "threads": "v1.7.0"
  }
}

babel.config.json

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "entry",
        "corejs": "3.22"
      },
    ]
  ]
}

webpack.config.js

const path = require('path');

const WorkerFileUpdaterPlugin = require('./worker-file-updater-plugin');

const HtmlWebPackPlugin = require('html-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const UnminifiedWebpackPlugin = require('unminified-webpack-plugin');
const ThreadsPlugin = require('threads-plugin');
const WebpackBeforeBuildPlugin = require('before-build-webpack');
const fs = require('fs');

// the WaitPlugin is copypasta from:                                                                                                                                                                                                                                                                                              
// https://www.viget.com/articles/run-multiple-webpack-configs-sequentially/                                                                                                                                                                                                                                                      
class WaitPlugin extends WebpackBeforeBuildPlugin {
  constructor(file, interval = 100, timeout = 10000) {
    super(function (stats, callback) {
      let start = Date.now();

      function poll() {
	if (fs.existsSync(file)) {
          callback();
	} else if (Date.now() - start > timeout) {
          throw Error(
            `Waited too long for the target file (${file}) to be generated. Exiting.`,
          );
	} else {
          setTimeout(poll, interval);
	}
      }

      poll();
    });
  }
}

const workerConfig = {
  output: {
    filename: 'worker.js',
    path: path.resolve(__dirname, 'dist'),
  },
  entry: {
    "webworker" : path.resolve(__dirname, 'src/bam-fetcher-worker'),
  },
  target: 'webworker',
  plugins: [new UnminifiedWebpackPlugin(), new ThreadsPlugin(), new WorkerFileUpdaterPlugin()],
};

const libraryConfig = {
  output: {
    filename: 'higlass-pileup.min.js',
    library: 'higlass-pileup',
    libraryTarget: 'umd',
    path: path.resolve(__dirname, 'dist'),
  },
  devServer: {
    contentBase: [path.join(__dirname, 'node_modules/higlass/dist')],
    watchContentBase: true,
    writeToDisk: true,
  },
  optimization: {
    minimizer: [
      new TerserPlugin()
    ],
    splitChunks: {
      cacheGroups: {
        styles: {
          name: 'index',
          test: /\.css$/,
          chunks: 'all',
          enforce: true,
        },
      },
    },
  },
  module: {
    rules: [
      // Run ESLint first                                                                                                                                                                                                                                                                                                         
      /*                                                                                                                                                                                                                                                                                                                          
      {                                                                                                                                                                                                                                                                                                                           
        enforce: 'pre',                                                                                                                                                                                                                                                                                                           
        test: /\.js$/,                                                                                                                                                                                                                                                                                                            
        exclude: /node_modules/,                                                                                                                                                                                                                                                                                                  
        use: {                                                                                                                                                                                                                                                                                                                    
          loader: 'eslint-loader',                                                                                                                                                                                                                                                                                                
        },                                                                                                                                                                                                                                                                                                                        
      },                                                                                                                                                                                                                                                                                                                          
      */
      // Transpile the ESD6 files to ES5                                                                                                                                                                                                                                                                                          
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
      // Extract them HTML files                                                                                                                                                                                                                                                                                                  
      {
        test: /\.html$/,
        use: [
          {
            loader: 'html-loader',
            options: { minimize: true },
          },
        ],
      },
      {
        test: /.*\.(gif|png|jpe?g|svg)$/i,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: 'images/[name].[ext]',
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: './src/index.html',
      filename: './index.html',
    }),
    new UnminifiedWebpackPlugin(),
    new ThreadsPlugin(),
    new WaitPlugin('dist/worker.js'),
  ],
};

module.exports = [workerConfig, libraryConfig];

Are there any thoughts on what I am missing in applying the workaround? I am happy to send more details, as needed. Thanks for any guidance.

alexpreynolds avatar Nov 28 '23 09:11 alexpreynolds