diff --git a/src/WorkerPool.js b/src/WorkerPool.js index d45769f..f565f46 100644 --- a/src/WorkerPool.js +++ b/src/WorkerPool.js @@ -212,20 +212,35 @@ class PoolWorker { break; } case 'resolve': { - const { context, request, questionId } = message; + const { context, request, options, questionId } = message; const { data } = this.jobs[id]; - data.resolve(context, request, (error, result) => { - this.writeJson({ - type: 'result', - id: questionId, - error: error ? { - message: error.message, - details: error.details, - missing: error.missing, - } : null, - result, + if (options) { + data.getResolve(options)(context, request, (error, result) => { + this.writeJson({ + type: 'result', + id: questionId, + error: error ? { + message: error.message, + details: error.details, + missing: error.missing, + } : null, + result, + }); }); - }); + } else { + data.resolve(context, request, (error, result) => { + this.writeJson({ + type: 'result', + id: questionId, + error: error ? { + message: error.message, + details: error.details, + missing: error.missing, + } : null, + result, + }); + }); + } finalCallback(); break; } diff --git a/src/index.js b/src/index.js index cecf2c3..3c8b6a4 100644 --- a/src/index.js +++ b/src/index.js @@ -22,6 +22,7 @@ function pitch() { emitWarning: this.emitWarning, loadModule: this.loadModule, resolve: this.resolve, + getResolve: this.getResolve, target: this.target, minimize: this.minimize, resourceQuery: this.resourceQuery, diff --git a/src/worker.js b/src/worker.js index e8fd3ba..6475d4e 100644 --- a/src/worker.js +++ b/src/worker.js @@ -101,6 +101,18 @@ function writeJson(data) { const queue = asyncQueue(({ id, data }, taskCallback) => { try { + const resolveWithOptions = (context, request, callback, options) => { + callbackMap[nextQuestionId] = callback; + writeJson({ + type: 'resolve', + id, + questionId: nextQuestionId, + context, + request, + options, + }); + nextQuestionId += 1; + }; loaderRunner.runLoaders({ loaders: data.loaders, resource: data.resource, @@ -119,15 +131,20 @@ const queue = asyncQueue(({ id, data }, taskCallback) => { nextQuestionId += 1; }, resolve: (context, request, callback) => { - callbackMap[nextQuestionId] = callback; - writeJson({ - type: 'resolve', - id, - questionId: nextQuestionId, - context, - request, - }); - nextQuestionId += 1; + resolveWithOptions(context, request, callback); + }, + // eslint-disable-next-line consistent-return + getResolve: options => (context, request, callback) => { + if (callback) { + resolveWithOptions(context, request, callback, options); + } else { + return new Promise((resolve, reject) => { + resolveWithOptions(context, request, (err, result) => { + if (err) reject(err); + else resolve(result); + }, options); + }); + } }, emitWarning: (warning) => { writeJson({ diff --git a/test/sass-loader-example/_shared.scss b/test/sass-loader-example/_shared.scss new file mode 100644 index 0000000..67ce83e --- /dev/null +++ b/test/sass-loader-example/_shared.scss @@ -0,0 +1,3 @@ +body { + background: red; +} diff --git a/test/sass-loader-example/index.js b/test/sass-loader-example/index.js new file mode 100644 index 0000000..9907556 --- /dev/null +++ b/test/sass-loader-example/index.js @@ -0,0 +1,34 @@ +/* eslint-disable import/no-unresolved */ +// some file +import './style.scss?00'; +import './style.scss?01'; +import './style.scss?02'; +import './style.scss?03'; +import './style.scss?04'; +import './style.scss?05'; +import './style.scss?06'; +import './style.scss?07'; +import './style.scss?08'; +import './style.scss?09'; + +import './style.scss?10'; +import './style.scss?11'; +import './style.scss?12'; +import './style.scss?13'; +import './style.scss?14'; +import './style.scss?15'; +import './style.scss?16'; +import './style.scss?17'; +import './style.scss?18'; +import './style.scss?19'; + +import './style.scss?20'; +import './style.scss?21'; +import './style.scss?22'; +import './style.scss?23'; +import './style.scss?24'; +import './style.scss?25'; +import './style.scss?26'; +import './style.scss?27'; +import './style.scss?28'; +import './style.scss?29'; diff --git a/test/sass-loader-example/package-lock.json b/test/sass-loader-example/package-lock.json new file mode 100644 index 0000000..7822a9e --- /dev/null +++ b/test/sass-loader-example/package-lock.json @@ -0,0 +1,60 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "lodash-es": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz", + "integrity": "sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "react": { + "version": "16.6.3", + "resolved": "https://registry.npmjs.org/react/-/react-16.6.3.tgz", + "integrity": "sha512-zCvmH2vbEolgKxtqXL2wmGCUxUyNheYn/C+PD1YAjfxHC54+MhdruyhO7QieQrYsYeTxrn93PM2y0jRH1zEExw==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.11.2" + }, + "dependencies": { + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "scheduler": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.11.3.tgz", + "integrity": "sha512-i9X9VRRVZDd3xZw10NY5Z2cVMbdYg6gqFecfj79USv1CFN+YrJ3gIPRKf1qlY+Sxly4djoKdfx1T+m9dnRB8kQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } + } + } +} diff --git a/test/sass-loader-example/package.json b/test/sass-loader-example/package.json new file mode 100644 index 0000000..d32f3fe --- /dev/null +++ b/test/sass-loader-example/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "lodash-es": "^4.17.14", + "react": "^16.6.3" + } +} diff --git a/test/sass-loader-example/style.scss b/test/sass-loader-example/style.scss new file mode 100644 index 0000000..f4daeb7 --- /dev/null +++ b/test/sass-loader-example/style.scss @@ -0,0 +1,5 @@ +@import '_shared'; + +body { + background: red; +} diff --git a/test/sass-loader-example/webpack.config.js b/test/sass-loader-example/webpack.config.js new file mode 100644 index 0000000..a87def2 --- /dev/null +++ b/test/sass-loader-example/webpack.config.js @@ -0,0 +1,62 @@ +const path = require('path'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // eslint-disable-line import/no-extraneous-dependencies +const threadLoader = require('../../src'); // eslint-disable-line import/no-extraneous-dependencies + +module.exports = (env) => { + const workerPool = { + workers: +env.threads, + poolTimeout: env.watch ? Infinity : 2000, + }; + const workerPoolSass = { + workers: +env.threads, + workerParallelJobs: 2, + poolTimeout: env.watch ? Infinity : 2000, + }; + if (+env.threads > 0) { + threadLoader.warmup(workerPool, ['babel-loader', 'babel-preset-env']); + threadLoader.warmup(workerPoolSass, ['sass-loader', 'css-loader']); + } + return { + mode: 'none', + context: __dirname, + entry: ['./index.js'], + output: { + path: path.resolve('dist'), + filename: 'bundle.js', + }, + module: { + rules: [ + { + test: /\.js$/, + use: [ + env.threads !== 0 && { + loader: path.resolve(__dirname, '../../dist/index.js'), + options: workerPool, + }, + 'babel-loader', + ].filter(Boolean), + }, + { + test: /\.scss$/, + use: [ + MiniCssExtractPlugin.loader, + env.threads !== 0 && { + loader: path.resolve(__dirname, '../../dist/index.js'), + options: workerPoolSass, + }, + 'css-loader', + 'sass-loader', + ].filter(Boolean), + }, + ], + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: 'style.css', + }), + ], + stats: { + children: false, + }, + }; +}; diff --git a/test/webpack.test.js b/test/webpack.test.js new file mode 100644 index 0000000..3db256e --- /dev/null +++ b/test/webpack.test.js @@ -0,0 +1,18 @@ +import webpack from 'webpack'; +import sassLoaderConfig from './sass-loader-example/webpack.config'; + +test("Processes sass-loader's @import correctly", (done) => { + const config = sassLoaderConfig({}); + webpack(config, (err, stats) => { + // eslint-disable-next-line no-console + if (err) console.error(err); + expect(err).toBe(null); + + if (stats.hasErrors()) { + // eslint-disable-next-line no-console + console.error(stats.toJson().errors); + } + expect(stats.hasErrors()).toBe(false); + done(); + }); +}, 30000);