From 0f24585e763a5d216f0a66a47337bcb79a2cc754 Mon Sep 17 00:00:00 2001 From: Ahmad Amireh Date: Mon, 8 Aug 2016 15:32:50 +0300 Subject: [PATCH] Add support for the loader API `this.loadModule()` Refs GH-66 --- README.md | 50 +++++++++------ examples/build-all.sh | 21 ++++--- examples/webpack2-extract-react/src/less.less | 4 +- examples/webpack2-extract-react/src/main.less | 1 + .../src/variables/variables.less | 2 + .../webpack.config--raw.js | 35 +++++++++++ .../webpack2-extract-react/webpack.config.js | 1 + lib/HappyFakeLoaderContext.js | 7 +++ lib/HappyRPCHandler.js | 13 +++- .../RPC--Loader__loadModule.test.js | 63 +++++++++++++++++++ 10 files changed, 166 insertions(+), 31 deletions(-) create mode 100644 examples/webpack2-extract-react/src/main.less create mode 100644 examples/webpack2-extract-react/src/variables/variables.less create mode 100644 examples/webpack2-extract-react/webpack.config--raw.js create mode 100644 lib/__tests__/integration/RPC--Loader__loadModule.test.js diff --git a/README.md b/README.md index f9fee3c..0b0a06d 100644 --- a/README.md +++ b/README.md @@ -326,13 +326,14 @@ Elapsed (ms) | Happy? | Cache enabled? | Cache present? | Using DLLs? | The builds above were run on Linux over a machine with 12 cores. -_TODO: test against other projects_ - ## Changes -**master** +**staging (master)** -- Fixed a regression in parsing loader "string chains" (multiple loaders specified in the same string separated by `!`), refs GH-68 +- Fixed a regression in scanning loader "string chains" (multiple loaders + specified in the same string separated by `!`), refs GH-68 +- Added support for the loader API `this.loadModule()` which is used by + less-loader, refs GH-66 **2.1.3** @@ -342,32 +343,39 @@ _TODO: test against other projects_ **2.1.2** -- Process argv will no longer be passed to the child processes spawned by HappyPack (#47) -- Support for the `target` loader context variable. Thanks to @Akkuma (#46) +- Process argv will no longer be passed to the child processes spawned by + HappyPack (refs GH-47) +- Support for the `target` loader context variable has been added. Thanks to + @Akkuma (refs GH-46) **2.1.1** -- Fix an issue with loading invalid/corrupt cache or source-map files. Big thanks to @benhughes for providing the patch in #42 +- Fixed an issue where happypack would crash when loading invalid/corrupt + cache or source-map files. Big thanks to @benhughes for providing the patch in GH-42 **2.1.0** -- SourceMap support +- Introduced SourceMap support **2.0.6** -- a new option `cacheSignatureGenerator` to handle use cases such as [#35] +- Introduced a new option `cacheSignatureGenerator` to handle use cases such + as [GH-35] **2.0.5** -- now using [mkdirp](https://github.com/substack/node-mkdirp) for creating the temp directory to support nested ones +- Now using [mkdirp](https://github.com/substack/node-mkdirp) for creating the + temp directory to support nested ones **2.0.4** -- fix an issue with cache not being utilized on node v0.10 (`fs.statSync` doesn't exist with that name there - thanks to [@XVincentX]) +- Fixed an issue where the cache was not being utilized on node v0.10 (since + `fs.statSync` doesn't exist with that name there) - thanks to [@XVincentX] **2.0.2** -- Fixed an issue that was causing loaders running in foreground to not receive the compiler options +- Fixed an issue that was causing loaders running in foreground to not receive + the compiler options **2.0.1** @@ -381,7 +389,8 @@ _TODO: test against other projects_ **1.1.4** -- Fixed an issue where the cache was being improperly invalidated due to `cacheContext` not being stored properly (#17, thanks to @blowery) +- Fixed an issue where the cache was being improperly invalidated due to + `cacheContext` not being stored properly (refs GH-17, thanks to @blowery) **1.1.3** @@ -389,23 +398,24 @@ _TODO: test against other projects_ **1.1.2** -- Fixed an issue on old node versions (0.10) with the EventEmitter API (#10) +- Fixed an issue on old node versions (0.10) with the EventEmitter API (GH-10) - Fixed an issue that was breaking the compiler if an invalid `threads` option was passed (evaluating to `NaN`) **1.1.1** -- Unrecognized and invalid config parameters will cause the process to abort. -- The active version is logged on launch. +- Unrecognized and invalid config parameters will now cause the process to + abort +- The active version is logged on launch **1.1.0** -- now supporting basic webpack loaders -- dropped the `transformer` parameter as it's no longer needed +- Now supporting basic webpack loaders +- Dropped the `transformer` parameter as it's no longer needed - `cache` now defaults to `true` -- now using a forking model utilizing node.js's `process.fork()` for cleaner +- Now using a forking model utilizing node.js's `process.fork()` for cleaner threading code **1.0.2** -- the loader will now accept IDs that aren't just numbers +- Loader will now accept IDs that aren't just numbers diff --git a/examples/build-all.sh b/examples/build-all.sh index 871a025..79b43a2 100755 --- a/examples/build-all.sh +++ b/examples/build-all.sh @@ -48,6 +48,7 @@ function babel_loader { grep "success" dist/main.js ) } + function babel_loader--webpack2 { echo "Testing HappyPack with babel-loader (webpack 2)" echo "-----------------------------------------------" @@ -55,10 +56,10 @@ function babel_loader--webpack2 { setup_example "examples/babel-loader--webpack2" ( - cd examples/babel-loader; - $WEBPACK_BIN --bail && - $WEBPACK_BIN --bail --config webpack.config--raw.js && - diff dist/main.js dist/main.raw.js && + cd examples/babel-loader--webpack2; + ./node_modules/.bin/webpack --bail && + ./node_modules/.bin/webpack --bail --config webpack.config--raw.js && + diff dist/main.js dist--raw/main.js && grep "success" dist/main.js ) } @@ -112,12 +113,12 @@ function webpack2 { ( cd examples/webpack2; - $WEBPACK_BIN --bail && + ./node_modules/.bin/webpack --bail && grep "console.log('success')" dist/main.js ) } -function webpack2ExtractText { +function webpack2-extract-text { echo "Testing HappyPack with webpack v2 + extract-text-plugins + react" echo "---------------------------------" @@ -125,7 +126,9 @@ function webpack2ExtractText { ( cd examples/webpack2-extract-react; - $WEBPACK_BIN --bail && + ./node_modules/.bin/webpack --bail --config webpack.config.js && + ./node_modules/.bin/webpack --bail --config webpack.config--raw.js && + diff dist/styles.css dist--raw/styles.css && grep "{ className: 'less scss' }," dist/main.js && grep ".less {" dist/styles.css ) @@ -177,7 +180,7 @@ run_task sass_loader run_task tslint_loader run_task transform_loader run_task webpack2 -run_task webpack2ExtractText +run_task webpack2-extract-text run_task source_maps run_task json_loader @@ -194,6 +197,6 @@ run_task sass_loader run_task transform_loader run_task webpack2 -run_task webpack2ExtractText +run_task webpack2-extract-text run_task source_maps run_task json_loader diff --git a/examples/webpack2-extract-react/src/less.less b/examples/webpack2-extract-react/src/less.less index 853eed3..8fe8d53 100644 --- a/examples/webpack2-extract-react/src/less.less +++ b/examples/webpack2-extract-react/src/less.less @@ -1,3 +1,5 @@ +@import "./main"; + .less { - color: red; + color: @color-red; } diff --git a/examples/webpack2-extract-react/src/main.less b/examples/webpack2-extract-react/src/main.less new file mode 100644 index 0000000..cb96d6b --- /dev/null +++ b/examples/webpack2-extract-react/src/main.less @@ -0,0 +1 @@ +@import "./variables/variables"; \ No newline at end of file diff --git a/examples/webpack2-extract-react/src/variables/variables.less b/examples/webpack2-extract-react/src/variables/variables.less new file mode 100644 index 0000000..1c3460f --- /dev/null +++ b/examples/webpack2-extract-react/src/variables/variables.less @@ -0,0 +1,2 @@ +@color-red: red; +@color-gray: #77808b; \ No newline at end of file diff --git a/examples/webpack2-extract-react/webpack.config--raw.js b/examples/webpack2-extract-react/webpack.config--raw.js new file mode 100644 index 0000000..d013d96 --- /dev/null +++ b/examples/webpack2-extract-react/webpack.config--raw.js @@ -0,0 +1,35 @@ +var path = require('path'); +var ExtractTextPlugin = require('extract-text-webpack-plugin'); +var webpack = require('webpack'); + +module.exports = { + entry: path.resolve(__dirname, 'src/index.js'), + output: { + path: path.resolve(__dirname, 'dist--raw'), + filename: '[name].js' + }, + module: { + loaders: [ + { + test: /\.js$/, + loader: 'babel' + }, { + test: /\.less$/, + loader: ExtractTextPlugin.extract({ + fallbackLoader: 'style', + loader: 'css!less' + }) + }, { + test: /\.scss$/, + loader: ExtractTextPlugin.extract({ + fallbackLoader: 'style', + loader: 'css!sass' + }) + } + ] + }, + plugins: [ + new webpack.optimize.OccurrenceOrderPlugin(), + new ExtractTextPlugin('styles.css'), + ] +} diff --git a/examples/webpack2-extract-react/webpack.config.js b/examples/webpack2-extract-react/webpack.config.js index 3c5ce20..38c9c28 100644 --- a/examples/webpack2-extract-react/webpack.config.js +++ b/examples/webpack2-extract-react/webpack.config.js @@ -31,6 +31,7 @@ module.exports = { ] }, plugins: [ + new webpack.optimize.OccurrenceOrderPlugin(), new ExtractTextPlugin('styles.css'), createHappyPlugin('js', ['babel']), createHappyPlugin('less', ['css!less']), diff --git a/lib/HappyFakeLoaderContext.js b/lib/HappyFakeLoaderContext.js index 4d1f82c..9ffdf5a 100644 --- a/lib/HappyFakeLoaderContext.js +++ b/lib/HappyFakeLoaderContext.js @@ -87,6 +87,13 @@ function HappyFakeLoaderContext(initialValues) { }); }; + loader.loadModule = function(resource, done) { + loader._compiler._sendMessage('loadModule', { + remoteLoaderId: loader._remoteLoaderId, + file: resource, + }, done); + }; + // alias loader.dependency = loader.addDependency; diff --git a/lib/HappyRPCHandler.js b/lib/HappyRPCHandler.js index e696487..55382b5 100644 --- a/lib/HappyRPCHandler.js +++ b/lib/HappyRPCHandler.js @@ -18,11 +18,19 @@ HappyRPCHandler.unregisterActiveLoader = function(id) { HappyRPCHandler.execute = function(type, payload, done) { var loader; + var resolve, resolver; if (type === 'resolve') { assertCompilerIsActive(); + resolver = activeCompiler.resolvers.normal; + resolve = activeCompiler.resolvers.normal.resolve; - activeCompiler.resolvers.normal.resolve(payload.context, payload.resource, done); + if (resolve.length === 4) { + resolve.call(resolver, payload.context, payload.context, payload.resource, done); + } + else { + resolve.call(resolver, payload.context, payload.resource, done); + } } else { // a loader RPC: assertLoaderIsActive(payload.remoteLoaderId); @@ -46,6 +54,9 @@ HappyRPCHandler.execute = function(type, payload, done) { else if (type === 'clearDependencies') { loader.clearDependencies(); } + else if (type === 'loadModule') { + loader.loadModule(payload.file, done); + } else { assert(false, "Unrecognized RPC '" + type + '"'); } diff --git a/lib/__tests__/integration/RPC--Loader__loadModule.test.js b/lib/__tests__/integration/RPC--Loader__loadModule.test.js new file mode 100644 index 0000000..0caf21b --- /dev/null +++ b/lib/__tests__/integration/RPC--Loader__loadModule.test.js @@ -0,0 +1,63 @@ +var fs = require('fs'); +var multiline = require('multiline-slash'); +var webpack = require('webpack'); +var assert = require('chai').assert; +var HappyPlugin = require('../../HappyPlugin'); +var TestUtils = require('../../HappyTestUtils'); + +describe('[Integration] Loader RPCs - this.loadModule()', function() { + var testSuite = TestUtils.IntegrationSuite2(this); + + it('works', function(done) { + var loader = testSuite.createLoaderFromString(multiline(function() { + // module.exports = function() { + // var callback = this.async(); + // + // this.loadModule('./b.js', function(err, contents) { + // if (err) { + // return callback(err); + // } + // + // callback(null, '// loaded file: "' + contents + '";'); + // }); + // }; + })); + + var file1 = testSuite.createFile('src/a.js', '// a.js'); + testSuite.createFile('src/b.js', 'lolol'); + + var compiler = webpack({ + entry: file1.path, + + output: { + path: testSuite.createDirectory('dist').path, + }, + + module: { + loaders: [{ + test: file1.path, + loader: TestUtils.HAPPY_LOADER_PATH + }] + }, + + plugins: [ + new HappyPlugin({ + loaders: [ loader.path ], + }) + ] + }); + + compiler.run(function(err, rawStats) { + if (TestUtils.assertNoWebpackErrors(err, rawStats, done)) { + return; + } + + assert.match( + fs.readFileSync(testSuite.resolve('dist/bundle.js'), 'utf-8'), + '// loaded file: "lolol";' + ); + + done(); + }); + }); +}); \ No newline at end of file