/* * This file is part of the Symfony Webpack Encore package. * * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ 'use strict'; const webpack = require('webpack'); // eslint-disable-line no-unused-vars const EncoreProxy = require('./lib/EncoreProxy'); const WebpackConfig = require('./lib/WebpackConfig'); const configGenerator = require('./lib/config-generator'); const validator = require('./lib/config/validator'); const parseRuntime = require('./lib/config/parse-runtime'); const context = require('./lib/context'); let runtimeConfig = context.runtimeConfig; let webpackConfig = runtimeConfig ? new WebpackConfig(runtimeConfig, true) : null; class Encore { /** * The directory where your files should be output. * * If relative (e.g. web/build), it will be set relative * to the directory where your package.json lives. * * @param {string} outputPath * @returns {Encore} */ setOutputPath(outputPath) { webpackConfig.setOutputPath(outputPath); return this; } /** * The public version of outputPath: the public path to outputPath. * * For example, if "web" is your document root, then: * * ``` * Encore * .setOutputPath('web/build') * .setPublicPath('/build') * ``` * * This can also be set to an absolute URL if you're using * a CDN: publicPath is used as the prefix to all asset paths * in the manifest.json file and internally in webpack: * * ``` * Encore * .setOutputPath('web/build') * .setPublicPath('https://coolcdn.com') * // needed when public path is absolute * .setManifestKeyPrefix('/build') * ``` * * @param {string} publicPath * @returns {Encore} */ setPublicPath(publicPath) { webpackConfig.setPublicPath(publicPath); return this; } /** * Used as a prefix to the *keys* in manifest.json. Not usually needed. * * You don't normally need to set this. When you *do* need to set * it, an error will notify you. * * Typically, publicPath is used in the keys inside manifest.json. * But if publicPath is absolute, then we require you to set this. * For example: * * ``` * Encore * .setOutputPath('web/build') * .setPublicPath('https://coolcdn.com/FOO') * .setManifestKeyPrefix('build/') * ``` * * The manifest.json file would look something like this: * * ``` * { * "build/main.js": "https://coolcdn.com/FOO/main.a54f3ccd2.js" * } * ``` * * @param {string} manifestKeyPrefix * @returns {Encore} */ setManifestKeyPrefix(manifestKeyPrefix) { webpackConfig.setManifestKeyPrefix(manifestKeyPrefix); return this; } /** * Allows you to configure the options passed to the DefinePlugin. * A list of available options can be found at https://webpack.js.org/plugins/define-plugin/ * * For example: * * ``` * Encore.configureDefinePlugin((options) => { * options.VERSION = JSON.stringify('1.0.0'); * }) * ``` * * @param {function} definePluginOptionsCallback * @returns {Encore} */ configureDefinePlugin(definePluginOptionsCallback = () => {}) { webpackConfig.configureDefinePlugin(definePluginOptionsCallback); return this; } /** * Allows you to configure the options passed to the @nuxt/friendly-errors-webpack-plugin. * A list of available options can be found at https://github.com/nuxt/friendly-errors-webpack-plugin * * For example: * * ``` * Encore.configureFriendlyErrorsPlugin((options) => { * options.clearConsole = true; * }) * ``` * * @param {function} friendlyErrorsPluginOptionsCallback * @returns {Encore} */ configureFriendlyErrorsPlugin(friendlyErrorsPluginOptionsCallback = () => {}) { webpackConfig.configureFriendlyErrorsPlugin(friendlyErrorsPluginOptionsCallback); return this; } /** * Allows you to configure the options passed to webpack-manifest-plugin. * A list of available options can be found at https://github.com/danethurber/webpack-manifest-plugin * * For example: * * ``` * Encore.configureManifestPlugin((options) => { * options.fileName = '../../var/assets/manifest.json'; * }) * ``` * * @param {function} manifestPluginOptionsCallback * @returns {Encore} */ configureManifestPlugin(manifestPluginOptionsCallback = () => {}) { webpackConfig.configureManifestPlugin(manifestPluginOptionsCallback); return this; } /** * Allows you to configure the options passed to the terser-webpack-plugin. * A list of available options can be found at https://github.com/webpack-contrib/terser-webpack-plugin * * For example: * * ``` * Encore.configureTerserPlugin((options) => { * options.cache = true; * options.terserOptions = { * output: { * comments: false * } * } * }) * ``` * * @param {function} terserPluginOptionsCallback * @returns {Encore} */ configureTerserPlugin(terserPluginOptionsCallback = () => {}) { webpackConfig.configureTerserPlugin(terserPluginOptionsCallback); return this; } /** * Allows you to configure the options passed to the css-minimizer-webpack-plugin. * A list of available options can be found at https://github.com/webpack-contrib/css-minimizer-webpack-plugin * * For example: * * ``` * Encore.configureCssMinimizerPlugin((options) => { * options.parallel = false; * }) * ``` * * @param {function} cssMinimizerPluginOptionsCallback * @returns {Encore} */ configureCssMinimizerPlugin(cssMinimizerPluginOptionsCallback = () => {}) { webpackConfig.configureCssMinimizerPlugin(cssMinimizerPluginOptionsCallback); return this; } /** * Adds a JavaScript file that should be webpacked: * * ``` * // final output file will be main.js in the output directory * Encore.addEntry('main', './path/to/some_file.js'); * ``` * * If the JavaScript file imports/requires CSS/Sass/LESS files, * then a CSS file (e.g. main.css) will also be output. * * @param {string} name The name (without extension) that will be used * as the output filename (e.g. app will become app.js) * in the output directory. * @param {string|Array} src The path to the source file (or files) * @returns {Encore} */ addEntry(name, src) { webpackConfig.addEntry(name, src); return this; } /** * Adds a collection of JavaScript files that should be webpacked: * * ``` * // final output file will be main.js in the output directory * Encore.addEntries({ * main: './path/to/some_file.js', * secondary: './path/to/another_file.js', * }); * ``` * * If the JavaScript files imports/requires CSS/Sass/LESS files, * then a CSS file (e.g. main.css) will also be output. * * @param {Object.} entries where the Keys are the * names (without extension) that will be used * as the output filename (e.g. app will become app.js) * in the output directory. The values are the path(s) * to the source file(s). * @returns {Encore} */ addEntries(entries) { webpackConfig.addEntries(entries); return this; } /** * Adds a CSS/SASS/LESS file that should be webpacked: * * ``` * // final output file will be main.css in the output directory * Encore.addStyleEntry('main', './path/to/some_file.css'); * ``` * * This is actually not something Webpack does natively, and you * should avoid using this function when possible. A better option * is to use addEntry() and then require/import your CSS files from * within your JavaScript files. * * @param {string} name The name (without extension) that will be used * as the output filename (e.g. app will become app.css) * in the output directory. * @param {string|Array} src The path to the source file (or files) * @returns {Encore} */ addStyleEntry(name, src) { webpackConfig.addStyleEntry(name, src); return this; } /** * Add a plugin to the sets of plugins already registered by Encore * * For example, if you want to add the "webpack.IgnorePlugin()", then: * * ``` * Encore.addPlugin(new webpack.IgnorePlugin(requestRegExp, contextRegExp)) * ``` * * By default custom plugins are added after the ones managed by Encore * but you can also set a priority to define where your plugin will be * added in the generated Webpack config. * * For example, if a plugin has a priority of 0 and you want to add * another plugin after it, then: * * ``` * Encore.addPlugin(new MyWebpackPlugin(), -10) * ``` * * The priority of each plugin added by Encore can be found in the * "lib/plugins/plugin-priorities.js" file. It is recommended to use * these constants if you want to add a plugin using the same priority * as one managed by Encore in order to avoid backward compatibility * breaks. * * For example, if you want one of your plugins to have the same priority * than the DefinePlugin: * * ``` * const Encore = require('@symfony/webpack-encore'); * const PluginPriorities = require('@symfony/webpack-encore/lib/plugins/plugin-priorities.js'); * * Encore.addPlugin(new MyWebpackPlugin(), PluginPriorities.DefinePlugin); * ``` * * @param {object} plugin * @param {number} priority * @returns {Encore} */ addPlugin(plugin, priority = 0) { webpackConfig.addPlugin(plugin, priority); return this; } /** * Adds a custom loader config * * @param {object} loader The loader config object * * @returns {Encore} */ addLoader(loader) { webpackConfig.addLoader(loader); return this; } /** * Alias to addLoader * * @param {object} rule * * @returns {Encore} */ addRule(rule) { this.addLoader(rule); return this; } /** * Allow you to add aliases that will be used by * Webpack when trying to resolve modules. * * See https://webpack.js.org/configuration/resolve/#resolve-alias * * For example: * * ``` * Encore.addAliases({ * Utilities: path.resolve(__dirname, 'src/utilities/'), * Templates: path.resolve(__dirname, 'src/templates/') * }) * ``` * * @param {object} aliases * * @returns {Encore} */ addAliases(aliases) { webpackConfig.addAliases(aliases); return this; } /** * Allow you to exclude some dependencies from the output bundles. * * See https://webpack.js.org/configuration/externals/ * * For example: * * ``` * Encore.addExternals({ * jquery: 'jQuery', * react: 'react' * }); * ``` * * Or: * * ``` * const nodeExternals = require('webpack-node-externals'); * * Encore.addExternals( * nodeExternals() * ); * * // or add multiple things at once * Encore.addExternals([ * nodeExternals(), * /^(jquery|\$)$/i * ]); * ``` * * @param {*} externals * * @returns {Encore} */ addExternals(externals) { webpackConfig.addExternals(externals); return this; } /** * When enabled, files are rendered with a hash based * on their contents (e.g. main.a2b61cc.js) * * A manifest.json file will be rendered to the output * directory with a map from the original file path to * the versioned path (e.g. `builds/main.js` => `builds/main.a2b61cc.js`) * * Note that the versioning must be disabled if you * want to use the dev-server. * * For example: * * ``` * Encore.enableVersioning(Encore.isProduction()); * ``` * * @param {boolean} enabled * @returns {Encore} */ enableVersioning(enabled = true) { webpackConfig.enableVersioning(enabled); return this; } /** * When enabled, all final CSS and JS files will be rendered * with sourcemaps to help debugging. * * The *type* of source map will differ between a development * or production build. * * For example if you want to always generate sourcemaps: * * ``` * Encore.enableSourceMaps(); * ``` * * Or only enable them when not in production mode: * * ``` * Encore.enableSourceMaps(!Encore.isProduction()); * ``` * * @param {boolean} enabled * @returns {Encore} */ enableSourceMaps(enabled = true) { webpackConfig.enableSourceMaps(enabled); return this; } /** * Add a new cache group to Webpack's SplitChunksPlugin. * This can, for instance, be used to extract code that * is common to multiple entries into its own chunk. * * See: https://webpack.js.org/plugins/split-chunks-plugin/#examples * * For example: * * ``` * Encore.addCacheGroup('vendor', { * test: /[\\/]node_modules[\\/]react/ * }); * ``` * * You can pass all the options supported by the SplitChunksPlugin * but also the following shorthand provided by Encore: * * * `node_modules`: An array of `node_modules` packages names * * For example: * * ``` * Encore.addCacheGroup('vendor', { * node_modules: ['react', 'react-dom'] * }); * ``` * * At least one of the `test` or the `node_modules` option * should be provided. * * By default, the new cache group will be created with the * following options: * * `chunks` set to `"all"` * * `enforce` set to `true` * * `name` set to the value of the "name" parameter * * @param {string} name The chunk name (e.g. vendor to create a vendor.js) * @param {object} options Cache group option * @returns {Encore} */ addCacheGroup(name, options) { webpackConfig.addCacheGroup(name, options); return this; } /** * Copy files or folders to the build directory. * * For example: * * ``` * // Copy the content of a whole directory and its subdirectories * Encore.copyFiles({ from: './assets/images' }); * * // Only copy files matching a given pattern * Encore.copyFiles({ from: './assets/images', pattern: /\.(png|jpg|jpeg)$/ }) * * // Set the path the files are copied to * Encore.copyFiles({ * from: './assets/images', * pattern: /\.(png|jpg|jpeg)$/, * // to path is relative to the build directory * to: 'images/[path][name].[ext]' * }) * * // Version files * Encore.copyFiles({ * from: './assets/images', * to: 'images/[path][name].[hash:8].[ext]' * }) * * // Add multiple configs in a single call * Encore.copyFiles([ * { from: './assets/images' }, * { from: './txt', pattern: /\.txt$/ }, * ]); * * // Set the context path: files will be copied * // into an images/ directory in the output dir * Encore.copyFiles({ * from: './assets/images', * to: '[path][name].[hash:8].[ext]', * context: './assets' * }); * ``` * * Notes: * * No transformation is applied to the copied files (for instance * copying a CSS file won't minify it) * * Supported options: * * {string} from (mandatory) * The path of the source directory (mandatory) * * {RegExp|string} pattern (default: all files) * A regular expression (or a string containing one) that * the filenames must match in order to be copied * * {string} to (default: [path][name].[ext]) * Where the files must be copied to. You can add all the * placeholders supported by the file-loader. * https://github.com/webpack-contrib/file-loader#placeholders * * {boolean} includeSubdirectories (default: true) * Whether or not the copy should include subdirectories. * * {string} context (default: path of the source directory) * The context to use as a root path when copying files. * * @param {object|Array} configs * @returns {Encore} */ copyFiles(configs) { webpackConfig.copyFiles(configs); return this; } /** * Tell Webpack to output a separate runtime.js file. * * This file must be included via a script tag before all * other JavaScript files output by Encore. * * The runtime.js file is useful when you plan to include * multiple entry files on the same page (e.g. a layout.js entry * and a page-specific entry). If you are *not* including * multiple entries on the same page, you can safely disable * this - disableSingleRuntimeChunk() - and remove the extra script tags. * * If you *do* include multiple entry files on the same page, * disabling the runtime.js file has two important consequences: * A) Each entry file will contain the Webpack runtime, which * means each contains some code that is duplicated in the other. * B) If two entry files require the same module (e.g. jquery), * they will receive *different* objects - not the *same* object. * This can cause some confusion if you expect a "layout.js" entry * to be able to "initialize" some jQuery plugins, because the * jQuery required by the other entry will be a different instance, * and so won't have the plugins initialized on it. * * @returns {Encore} */ enableSingleRuntimeChunk() { webpackConfig.enableSingleRuntimeChunk(); return this; } /** * Tell Webpack to *not* output a separate runtime.js file. * * See enableSingleRuntimeChunk() for more details. * * @returns {Encore} */ disableSingleRuntimeChunk() { webpackConfig.disableSingleRuntimeChunk(); return this; } /** * Tell Webpack to "split" your entry chunks. * * This will mean that, instead of adding 1 script tag * to your page, your server-side code will need to read * the entrypoints.json file in the build directory to * determine the *multiple* .js (and .css) files that * should be included for each entry. * * This is a performance optimization, but requires extra * work (described above) to support this. * * @returns {Encore} */ splitEntryChunks() { webpackConfig.splitEntryChunks(); return this; } /** * Configure the optimization.splitChunks configuration. * * https://webpack.js.org/plugins/split-chunks-plugin/ * * ``` * Encore.configureSplitChunks(function(splitChunks) { * // change the configuration * splitChunks.minSize = 0; * }); * ``` * * @param {function} callback * @returns {Encore} */ configureSplitChunks(callback) { webpackConfig.configureSplitChunks(callback); return this; } /** * Configure the watchOptions and devServer.watchOptions configuration. * * https://webpack.js.org/configuration/watch/ * https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- * * ``` * Encore.configureWatchOptions(function(watchOptions) { * // change the configuration * watchOptions.poll = 250; // useful when running inside a Virtual Machine * }); * ``` * * @param {function} callback * @returns {Encore} */ configureWatchOptions(callback) { webpackConfig.configureWatchOptions(callback); return this; } /** * Configure the devServer configuration. * * https://webpack.js.org/configuration/dev-server * * ``` * Encore.configureDevServerOptions(function(options) { * // change the configuration * options.server = { * type: 'https', * options: { * key: '', * cert: '', * } * }; * }); * ``` * * @param {function} callback * @returns {Encore} */ configureDevServerOptions(callback) { webpackConfig.configureDevServerOptions(callback); return this; } /** * Automatically make some variables available everywhere! * * Usage: * * ``` * WebpackConfig.autoProvideVariables({ * $: 'jquery', * jQuery: 'jquery' * }); * ``` * * Then, whenever $ or jQuery are found in any * modules, webpack will automatically require * the "jquery" module so that the variable is available. * * This is useful for older packages, that might * expect jQuery (or something else) to be a global variable. * * @param {object} variables * @returns {Encore} */ autoProvideVariables(variables) { webpackConfig.autoProvideVariables(variables); return this; } /** * Makes jQuery available everywhere. Equivalent to * * ``` * WebpackConfig.autoProvideVariables({ * $: 'jquery', * jQuery: 'jquery', * 'window.jQuery': 'jquery' * }); * ``` * * @returns {Encore} */ autoProvidejQuery() { webpackConfig.autoProvidejQuery(); return this; } /** * Enables the postcss-loader * * Once enabled, you must have a postcss.config.js config file. * * https://github.com/postcss/postcss-loader * * ``` * Encore.enablePostCssLoader(); * ``` * * Or pass options to the loader * * ``` * Encore.enablePostCssLoader(function(options) { * // https://github.com/postcss/postcss-loader#options * // options.config = {...} * }) * ``` * * @param {function} postCssLoaderOptionsCallback * @returns {Encore} */ enablePostCssLoader(postCssLoaderOptionsCallback = () => {}) { webpackConfig.enablePostCssLoader(postCssLoaderOptionsCallback); return this; } /** * Call this if you plan on loading SASS files. * * ``` * Encore.enableSassLoader(); * ``` * * Or pass options to node-sass * * ``` * Encore.enableSassLoader(function(options) { * // https://github.com/sass/node-sass#options * // options.includePaths = [...] * }, { * // set optional Encore-specific options * // resolveUrlLoader: true * }); * ``` * * Supported options: * * {boolean} resolveUrlLoader (default=true) * Whether or not to use the resolve-url-loader. * Setting to false can increase performance in some * cases, especially when using bootstrap_sass. But, * when disabled, all url()'s are resolved relative * to the original entry file... not whatever file * the url() appears in. * * {object} resolveUrlLoaderOptions (default={}) * Options parameters for resolve-url-loader * // https://www.npmjs.com/package/resolve-url-loader#options * * @param {function} sassLoaderOptionsCallback * @param {object} encoreOptions * @returns {Encore} */ enableSassLoader(sassLoaderOptionsCallback = () => {}, encoreOptions = {}) { webpackConfig.enableSassLoader(sassLoaderOptionsCallback, encoreOptions); return this; } /** * Call this if you plan on loading less files. * * ``` * Encore.enableLessLoader(); * ``` * * Or pass options to the loader * * ``` * Encore.enableLessLoader(function(options) { * // https://github.com/webpack-contrib/less-loader#examples * // http://lesscss.org/usage/#command-line-usage-options * // options.relativeUrls = false; * }); * ``` * * @param {function} lessLoaderOptionsCallback * @returns {Encore} */ enableLessLoader(lessLoaderOptionsCallback = () => {}) { webpackConfig.enableLessLoader(lessLoaderOptionsCallback); return this; } /** * Call this if you plan on loading stylus files. * * ``` * Encore.enableStylusLoader(); * ``` * * Or pass options to the loader * * ``` * Encore.enableStylusLoader(function(options) { * // https://github.com/shama/stylus-loader * // options.import = ['~library/index.styl']; * }); * ``` * * @param {function} stylusLoaderOptionsCallback * @returns {Encore} */ enableStylusLoader(stylusLoaderOptionsCallback = () => {}) { webpackConfig.enableStylusLoader(stylusLoaderOptionsCallback); return this; } /** * Configure babel, without needing a .babelrc file. * * https://babeljs.io/docs/usage/babelrc/ * * ``` * Encore.configureBabel(function(babelConfig) { * // change the babelConfig * // if you use an external Babel configuration * // this callback will NOT be used. In this case * // you can pass null as the first parameter to * // still be able to use some of the options below * // without a warning. * }, { * // set optional Encore-specific options, for instance: * * // change the rule that determines which files * // won't be processed by Babel * exclude: /bower_components/ * * // ...or keep the default rule but only allow * // *some* Node modules to be processed by Babel * includeNodeModules: ['foundation-sites'] * * // automatically import polyfills where they * // are needed * useBuiltIns: 'usage' * * // if you set useBuiltIns you also have to add * // core-js to your project using Yarn or npm and * // inform Babel of the version it will use. * corejs: 3 * }); * ``` * * Supported options: * * {Condition} exclude (default=/(node_modules|bower_components)/) * A Webpack Condition passed to the JS/JSX rule that * determines which files and folders should not be * processed by Babel (https://webpack.js.org/configuration/module/#condition). * Can be used even if you have an external Babel configuration * (a babel.config.json file for instance) * Warning: .babelrc config files don't apply to node_modules. Use * babel.config.json instead to apply the same config to modules if * they are not excluded anymore. * Cannot be used if the "includeNodeModules" option is * also set. * * {string[]} includeNodeModules * If set that option will include the given Node modules to * the files that are processed by Babel. * Can be used even if you have an external Babel configuration * (a babel.config.json file for instance). * Warning: .babelrc config files don't apply to node_modules. Use * babel.config.json instead to apply the same config to these modules. * Cannot be used if the "exclude" option is also set * * {'usage'|'entry'|false} useBuiltIns (default=false) * Set the "useBuiltIns" option of @babel/preset-env that changes * how it handles polyfills (https://babeljs.io/docs/en/babel-preset-env#usebuiltins) * Using it with 'entry' will require you to import core-js * once in your whole app and will result in that import being replaced * by individual polyfills. Using it with 'usage' will try to * automatically detect which polyfills are needed for each file and * add them accordingly. * Cannot be used if you have an external Babel configuration (a .babelrc * file for instance). In this case you can set the option directly into * that configuration file. * * {number|string|object} corejs (default=not set) * Set the "corejs" option of @babel/preset-env. * It should contain the version of core-js you added to your project * if useBuiltIns isn't set to false. * * @param {function|null} callback * @param {object} encoreOptions * @returns {Encore} */ configureBabel(callback, encoreOptions = {}) { webpackConfig.configureBabel(callback, encoreOptions); return this; } /** * Configure @babel/preset-env * * https://babeljs.io/docs/en/babel-preset-env * * ``` * Encore.configureBabelPresetEnv(function(options) { * // change the @babel/preset-env config * // if you use an external Babel configuration * // this callback will NOT be used * // options.corejs = 3; * // options.useBuiltIns = 'usage'; * // ... * }); * ``` * * @param {function} callback * @returns {Encore} */ configureBabelPresetEnv(callback) { webpackConfig.configureBabelPresetEnv(callback); return this; } /** * Configure the css-loader. * * https://github.com/webpack-contrib/css-loader#options * * ``` * Encore.configureCssLoader(function(config) { * // change the config * // config.minimize = true; * }); * ``` * * @param {function} callback * @returns {Encore} */ configureCssLoader(callback) { webpackConfig.configureCssLoader(callback); return this; } /** * If enabled, the Stimulus bridge is used to load Stimulus controllers from PHP packages. * * @param {string} controllerJsonPath Path to the controllers.json file. * @returns {Encore} */ enableStimulusBridge(controllerJsonPath) { webpackConfig.enableStimulusBridge(controllerJsonPath); return this; } /** * Enables & configures persistent build caching. * * https://webpack.js.org/blog/2020-10-10-webpack-5-release/#persistent-caching * * ``` * Encore.enableBuildCache({ * // object of "buildDependencies" * // https://webpack.js.org/configuration/other-options/#cachebuilddependencies * // __filename means that changes to webpack.config.js should invalidate the cache * config: [__filename], * }); ** * // also configure other options the Webpack "cache" key * Encore.enableBuildCache({ config: [__filename] }, (cache) => { * cache.version: `${process.env.GIT_REV}`; * * cache.name: `${env.target}` * }); * ``` * * @param {object} buildDependencies * @param {function} cacheCallback * @returns {Encore} */ enableBuildCache(buildDependencies, cacheCallback = (cache) => {}) { webpackConfig.enableBuildCache(buildDependencies, cacheCallback); return this; } /** * Configure the mini-css-extract-plugin. * * https://github.com/webpack-contrib/mini-css-extract-plugin#configuration * * ``` * Encore.configureMiniCssExtractPlugin( * function(loaderConfig) { * // change the loader's config * // loaderConfig.reloadAll = true; * }, * function(pluginConfig) { * // change the plugin's config * // pluginConfig.chunkFilename = '[id].css'; * } * ); * ``` * * @param {function} loaderOptionsCallback * @param {function} pluginOptionsCallback * @returns {Encore} */ configureMiniCssExtractPlugin(loaderOptionsCallback, pluginOptionsCallback = () => {}) { webpackConfig.configureMiniCssExtractPlugin(loaderOptionsCallback, pluginOptionsCallback); return this; } /** * If enabled, the react preset is added to Babel. * * https://babeljs.io/docs/plugins/preset-react/ * * @returns {Encore} */ enableReactPreset() { webpackConfig.enableReactPreset(); return this; } /** * If enabled, a Preact preset will be applied to * the generated Webpack and Babel configuration. * * ``` * Encore.enablePreactPreset() * ``` * * If you wish to also use preact-compat (https://github.com/developit/preact-compat) * you can enable it by setting the "preactCompat" option to true: * * ``` * Encore.enablePreactPreset({ preactCompat: true }) * ``` * * @param {object} options * @returns {Encore} */ enablePreactPreset(options = {}) { webpackConfig.enablePreactPreset(options); return this; } /** * Call this to process TypeScript files through ts-loader. * * ``` * Encore.enableTypeScriptLoader() * ``` * * Or see Encore.enableBabelTypeScriptPreset() for a faster * method of processing TypeScript files. * * Or, configure the ts-loader options: * * ``` * Encore.enableTypeScriptLoader(function(tsConfig) { * // https://github.com/TypeStrong/ts-loader/blob/master/README.md#loader-options * // tsConfig.silent = false; * }); * ``` * * @param {function} callback * @returns {Encore} */ enableTypeScriptLoader(callback = () => {}) { webpackConfig.enableTypeScriptLoader(callback); return this; } /** * Call this to enable forked type checking for TypeScript loader * https://github.com/TypeStrong/ts-loader/blob/v2.3.0/README.md#faster-builds * * This is a build optimization API to reduce build times. * * @param {function} forkedTypeScriptTypesCheckOptionsCallback * @returns {Encore} */ enableForkedTypeScriptTypesChecking(forkedTypeScriptTypesCheckOptionsCallback = () => {}) { webpackConfig.enableForkedTypeScriptTypesChecking( forkedTypeScriptTypesCheckOptionsCallback ); return this; } /** * If enabled, a TypeScript preset will be applied to * the generated Webpack and Babel configuration. * * ``` * Encore.enableBabelTypeScriptPreset() * ``` * * This method lets Babel handle your TypeScript code * and cannot be used with `Encore.enableTypeScriptLoader()` * or `Encore.enableForkedTypeScriptTypesChecking()`. * * Since all types are removed by Babel, * you must run `tsc --noEmit` yourself for type checking. * * The Babel TypeScript preset can be configured, * see https://babeljs.io/docs/en/babel-preset-typescript#options * for available options. * * For example: * ``` * Encore.enableBabelTypeScriptPreset({ * isTSX: true * }) * ``` * * @param {object} options * @returns {Encore} */ enableBabelTypeScriptPreset(options = {}) { webpackConfig.enableBabelTypeScriptPreset(options); return this; } /** * If enabled, the Vue.js loader is enabled. * * https://github.com/vuejs/vue-loader * * ``` * Encore.enableVueLoader(); * * // or configure the vue-loader options * // https://vue-loader.vuejs.org/en/configurations/advanced.html * Encore.enableVueLoader(function(options) { * options.preLoaders = { ... } * }); * ``` * * ``` * // or configure Encore-specific options * Encore.enableVueLoader(() => {}, { * // set optional Encore-specific options, for instance: * * // set to false to *only* include the smaller "runtime" * // build, which can't compile templates at runtime, but is * // CSP compliant/ * // set explicitly to true to silence the recommendation * runtimeCompilerBuild: false * * // use version 2 or 3 to force your Vue version * // otherwise, Encore will detect it automatically * version: 2 * * // enable JSX usage in Vue components * // https://vuejs.org/v2/guide/render-function.html#JSX * useJsx: true * }) * ``` * * Supported options: * * {boolean} useJsx (default=false) * Configure Babel to use the preset "@vue/babel-preset-jsx", * in order to enable JSX usage in Vue components. * * @param {function} vueLoaderOptionsCallback * @param {object} encoreOptions * @returns {Encore} */ enableVueLoader(vueLoaderOptionsCallback = () => {}, encoreOptions = {}) { webpackConfig.enableVueLoader(vueLoaderOptionsCallback, encoreOptions); return this; } /** * If enabled, the eslint-webpack-plugin is enabled. * * https://github.com/webpack-contrib/eslint-webpack-plugin * * ``` * // enables the eslint plugin using the default eslint configuration. * Encore.enableEslintPlugin(); * * // You can also pass in an object of options * // that will be passed on to the eslint-webpack-plugin * Encore.enableEslintPlugin({ * emitWarning: false * }); * * // For a more advanced usage you can pass in a callback * // https://github.com/webpack-contrib/eslint-webpack-plugin#options * Encore.enableEslintPlugin((options) => { * options.extensions.push('vue'); // to lint Vue files * options.emitWarning = false; * }); * ``` * * @param {string|object|function} eslintPluginOptionsOrCallback * @returns {Encore} */ enableEslintPlugin(eslintPluginOptionsOrCallback = () => {}) { webpackConfig.enableEslintPlugin(eslintPluginOptionsOrCallback); return this; } /** * If enabled, display build notifications using * webpack-notifier. * * https://github.com/Turbo87/webpack-notifier * * ``` * Encore.enableBuildNotifications(); * * // or configure the webpack-notifier options * // https://github.com/Turbo87/webpack-notifier#configuration * Encore.enableBuildNotifications(true, function(options) { * options.title = 'Webpack build'; * }); * ``` * * @param {boolean} enabled * @param {function} notifierPluginOptionsCallback * @returns {Encore} */ enableBuildNotifications(enabled = true, notifierPluginOptionsCallback = () => {}) { webpackConfig.enableBuildNotifications(enabled, notifierPluginOptionsCallback); return this; } /** * Call this if you plan on loading Handlebars files. * * ``` * Encore.enableHandlebarsLoader(); * ``` * * Or pass options to the loader * * ``` * Encore.enableHandlebarsLoader(function(options) { * // https://github.com/pcardune/handlebars-loader * // options.debug = true; * }); * ``` * * @param {function} callback * @returns {Encore} */ enableHandlebarsLoader(callback = () => {}) { webpackConfig.enableHandlebarsLoader(callback); return this; } /** * Call this if you don't want imported CSS to be extracted * into a .css file. All your styles will then be injected * into the page by your JS code. * * This can be useful when using the dev-server with hot * module reload (so that CSS can benefit from HMR): * * ``` * // disable CSS only when using the dev-server * Encore.disableCssExtraction(Encore.isDevServer()) * ``` * * Internally, this disables the mini-css-extract-plugin * and uses the style-loader instead. * @param {boolean} disabled * @returns {Encore} */ disableCssExtraction(disabled = true) { webpackConfig.disableCssExtraction(disabled); return this; } /** * Configure the style-loader. * The style-loader is used only if you also call Encore. disableCssExtraction(). * * https://github.com/webpack-contrib/style-loader#options * * ``` * Encore.configureStyleLoader(function(config) { * // change the config * // config.injectType = 'singletonStyleTag'; * }); * ``` * * @param {function} callback * @returns {Encore} */ configureStyleLoader(callback) { webpackConfig.configureStyleLoader(callback); return this; } /** * Call this to change how the name of each output * file is generated. * * ``` * Encore.configureFilenames({ * js: '[name].[contenthash].js', * css: '[name].[contenthash].css', * assets: 'assets/[name].[hash:8][ext]', * }); * ``` * * It's safe to omit a key (e.g. css): the default naming strategy * will be used for any file types not passed. * * If you are using Encore.enableVersioning() * make sure that your "js" and "css" filenames contain * "[contenthash]". * * The "assets" key is used for the output.assetModuleFilename option, * which is overridden for both fonts and images. See configureImageRule() * and configureFontRule() to control those filenames. * * @param {object} filenames * @returns {Encore} */ configureFilenames(filenames) { webpackConfig.configureFilenames(filenames); return this; } /** * Configure how images are loaded/processed under module.rules. * * https://webpack.js.org/guides/asset-modules/ * * The most important things can be controlled by passing * an options object to the first argument: * * ``` * Encore.configureImageRule({ * // common values: asset, asset/resource, asset/inline * // Using "asset" will allow smaller images to be "inlined" * // instead of copied. * // javascript/auto can be used to disable asset images (see next example) * type: 'asset/resource', * * // applicable when for "type: asset": files smaller than this * // size will be "inlined" into CSS, larger files will be extracted * // into independent files * maxSize: 4 * 1024, // 4 kb * * // control the output filename of images * filename: 'images/[name].[hash:8][ext]', * * // you can also fully disable the image rule if you want * // to control things yourself * enabled: true, * }); * ``` * * If you need more control, you can also pass a callback to the * 2nd argument. This will be passed the specific Rule object, * which you can modify: * * https://webpack.js.org/configuration/module/#rule * * ``` * Encore.configureImageRule({}, function(rule) { * // if you set "type: 'javascript/auto'" in the first argument, * // then you can now specify a loader manually * // rule.loader = 'file-loader'; * // rule.options = { filename: 'images/[name].[hash:8][ext]' } * }); * ``` * * @param {object} options * @param {string|object|function} ruleCallback * @returns {Encore} */ configureImageRule(options = {}, ruleCallback = (rule) => {}) { webpackConfig.configureImageRule(options, ruleCallback); return this; } /** * Configure how fonts are processed/loaded under module.rules. * * https://webpack.js.org/guides/asset-modules/ * * See configureImageRule() for more details. * * @param {object} options * @param {string|object|function} ruleCallback * @returns {Encore} */ configureFontRule(options = {}, ruleCallback = (rule) => {}) { webpackConfig.configureFontRule(options, ruleCallback); return this; } /** * Configure Webpack loaders rules (`module.rules`). * This is a low-level function, be careful when using it. * * https://webpack.js.org/concepts/loaders/#configuration * * ``` * Encore * .enableVueLoader() * .configureLoaderRule('vue', (loaderRule) => { * // some custom config for vue-loader * }); * ``` * * @param {string} name * @param {function} callback * @return {Encore} */ configureLoaderRule(name, callback) { webpackConfig.configureLoaderRule(name, callback); return this; } /** * If enabled, the output directory is emptied between each build (to remove old files). * * A list of available options can be found at https://github.com/johnagan/clean-webpack-plugin * * For example: * * ``` * Encore.cleanupOutputBeforeBuild(['*.js'], (options) => { * options.dry = true; * }) * ``` * * @param {Array} paths Paths that should be cleaned, relative to the "root" option * @param {function} cleanWebpackPluginOptionsCallback * @returns {Encore} */ cleanupOutputBeforeBuild(paths = ['**/*'], cleanWebpackPluginOptionsCallback = () => {}) { webpackConfig.cleanupOutputBeforeBuild(paths, cleanWebpackPluginOptionsCallback); return this; } /** * If enabled, add integrity hashes to the entrypoints.json * file for all the files it references. * * These hashes can then be used, for instance, in the "integrity" * attributes of