From ac0c869b86b98881ac5544bf7248c63a971b7219 Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Wed, 26 Sep 2018 22:21:47 -0700 Subject: [PATCH] Tweak the customize implementation to be a bit more strict. --- README.md | 22 +++++++++++++++++++--- src/index.js | 36 +++++++++++++++++++++++++++--------- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index ed2ae9ef..b816e272 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ This loader also supports the following loader-specific option: * `cacheCompression`: Default `true`. When set, each Babel transform output will be compressed with Gzip. If you want to opt-out of cache compression, set it to `false` -- your project may benefit from this if it transpiles thousands of files. -* `customize`: Default `null`. See [Customized Loader](#customized-loader). +* `customize`: Default `null`. The path of a module that exports a `custom` callback [like the one that you'd pass to `.custom()`](#customized-loader). Since you already have to make a new file to use this, it is recommended that you instead use `.custom` to create a wrapper loader. Only use this is you _must_ continue using `babel-loader` directly, but still want to customize. **Note**: The `sourceMap` option is ignored. Instead, source maps are automatically enabled when webpack is configured to use them (via the [`devtool`](https://webpack.js.org/configuration/devtool/#devtool) config option). @@ -210,12 +210,14 @@ of Babel's configuration for each file that it processes. `babel` so that tooling can ensure that it using exactly the same `@babel/core` instance as the loader itself. -This same callback can be provided under the `customize` key in the loader options. -You may also pass `customize` a file name which exports this callback. +In cases where you want to customize without actually having a file to call `.custom`, you +may also pass the `customize` option with a string pointing at a file that exports +your `custom` callback function. ### Example ```js +// Export from "./my-custom-loader.js" or whatever you want. module.exports = require("babel-loader").custom(babel => { function myPlugin() { return { @@ -263,6 +265,20 @@ module.exports = require("babel-loader").custom(babel => { }); ``` +```js +// And in your Webpack config +module.exports = { + // .. + module: { + rules: [{ + // ... + loader: path.join(__dirname, 'my-custom-loader.js'), + // ... + }] + } +}; +``` + ### `customOptions(options: Object): { custom: Object, loader: Object }` Given the loader's options, split custom options out of `babel-loader`'s diff --git a/src/index.js b/src/index.js index 92f55754..f657352d 100644 --- a/src/index.js +++ b/src/index.js @@ -23,6 +23,7 @@ const pkg = require("../package.json"); const cache = require("./cache"); const transform = require("./transform"); +const path = require("path"); const loaderUtils = require("loader-utils"); function subscribe(subscriber, metadata, context) { @@ -52,15 +53,32 @@ async function loader(source, inputSourceMap, overrides) { let loaderOptions = loaderUtils.getOptions(this) || {}; - overrides = overrides || loaderOptions.customize; - // customize may have been passed as a file, so we should load it - if (typeof overrides === "string") { - overrides = require(overrides); - } - // customize may have been passed as a function and not an object (to access - // the `babel` variable), so let's build the overrides - if (typeof overrides === "function") { - overrides = overrides(babel); + if (loaderOptions.customize != null) { + if (typeof loaderOptions.customize !== "string") { + throw new Error( + "Customized loaders must be implemented as standalone modules.", + ); + } + if (!path.isAbsolute(loaderOptions.customize)) { + throw new Error( + "Customized loaders must be passed as absolute paths, since " + + "babel-loader has no way to know what they would be relative to.", + ); + } + if (overrides) { + throw new Error( + "babel-loader's 'customize' option is not available when already " + + "using a customized babel-loader wrapper.", + ); + } + + let override = require(loaderOptions.customize); + if (override.__esModule) override = override.default; + + if (typeof override === "function") { + throw new Error("Custom overrides must be functions."); + } + overrides = override(babel); } let customOptions;