Skip to content

Instantly share code, notes, and snippets.

@Mukundhan-I2I
Forked from pleunv/babel-preset-react-app.js
Created February 24, 2020 12:34
Show Gist options
  • Save Mukundhan-I2I/b73c1ed743c1eaf89760574b8c8676d5 to your computer and use it in GitHub Desktop.
Save Mukundhan-I2I/b73c1ed743c1eaf89760574b8c8676d5 to your computer and use it in GitHub Desktop.
webpack 4 dev config
/* eslint-disable import/no-extraneous-dependencies, prefer-template */
// const validateBoolOption = (name, value, defaultValue) => {
// if (typeof value === 'undefined') {
// value = defaultValue;
// }
// if (typeof value !== 'boolean') {
// throw new Error(`Preset react-app: '${name}' option must be a boolean.`);
// }
// return value;
// };
module.exports = (api, opts) => {
if (!opts) {
opts = {};
}
// This is similar to how `env` works in Babel:
// https://babeljs.io/docs/usage/babelrc/#env-option
// We are not using `env` because it’s ignored in versions > babel-core@6.10.4:
// https://github.com/babel/babel/issues/4539
// https://github.com/facebook/create-react-app/issues/720
// It’s also nice that we can enforce `NODE_ENV` being specified.
const env = process.env.BABEL_ENV || process.env.NODE_ENV;
const isEnvDevelopment = env === 'development';
const isEnvProduction = env === 'production';
const isEnvTest = env === 'test';
// const isFlowEnabled = validateBoolOption('flow', opts.flow, true);
if (!isEnvDevelopment && !isEnvProduction && !isEnvTest) {
throw new Error(
'Using `babel-preset-react-app` requires that you specify `NODE_ENV` or ' +
'`BABEL_ENV` environment variables. Valid values are "development", ' +
'"test", and "production". Instead, received: ' +
JSON.stringify(env) +
'.'
);
}
return {
presets: [
isEnvTest && [
// ES features necessary for user's Node version
require('@babel/preset-env').default,
{
targets: {
node: '6.12'
}
}
],
(isEnvProduction || isEnvDevelopment) && [
// Latest stable ECMAScript features
require('@babel/preset-env').default,
{
// `entry` transforms `@babel/polyfill` into individual requires for
// the targeted browsers. This is safer than `usage` which performs
// static code analysis to determine what's required.
// This is probably a fine default to help trim down bundles when
// end-users inevitably import '@babel/polyfill'.
useBuiltIns: false,
include: [
'es6.map',
'es6.set'
],
// Do not transform modules to CJS
modules: false
}
],
[
require('@babel/preset-react').default,
{
// Adds component stack to warning messages
// Adds __self attribute to JSX which React will use for some warnings
development: isEnvDevelopment || isEnvTest,
// Will use the native built-in instead of trying to polyfill
// behavior for any plugins that require one.
useBuiltIns: true
}
]
].filter(Boolean),
plugins: [
// Experimental macros support. Will be documented after it's had some time
// in the wild.
// require('babel-plugin-macros'),
[
require('babel-plugin-emotion').default,
{
hoist: isEnvProduction,
sourceMap: isEnvDevelopment
}
],
// Necessary to include regardless of the environment because
// in practice some other transforms (such as object-rest-spread)
// don't work without it: https://github.com/babel/babel/issues/7215
// require('@babel/plugin-transform-destructuring').default,
// class { handleClick = () => { } }
// Enable loose mode to use assignment instead of defineProperty
// See discussion in https://github.com/facebook/create-react-app/issues/4263
[
require('@babel/plugin-proposal-class-properties').default,
{
loose: true
}
],
// The following two plugins use Object.assign directly, instead of Babel's
// extends helper. Note that this assumes `Object.assign` is available.
// { ...todo, completed: true }
[
require('@babel/plugin-proposal-object-rest-spread').default,
{
useBuiltIns: true
}
],
// Polyfills the runtime needed for async/await and generators
[
require('@babel/plugin-transform-runtime').default,
{
helpers: true,
polyfill: true,
regenerator: true,
moduleName: '@babel/runtime'
}
],
// isEnvProduction && [
// // Remove PropTypes from production build
// require('babel-plugin-transform-react-remove-prop-types').default,
// {
// removeImport: true,
// },
// ],
// function* () { yield 42; yield 43; }
isEnvProduction && require('@babel/plugin-transform-react-inline-elements').default,
require('@babel/plugin-syntax-dynamic-import').default,
require('@babel/plugin-proposal-export-default-from').default
// isEnvTest &&
// // Transform dynamic import to require
// require('babel-plugin-transform-dynamic-import').default,
].filter(Boolean)
};
};
/* eslint-disable import/no-extraneous-dependencies */
const loaderUtils = require('loader-utils');
module.exports = function getLocalIdent(context, localIdentName, localName, options) {
// Use the filename or folder name, based on some uses the index.js /
// index.module.css project style
const fileNameOrFolder = context.resourcePath.endsWith('index.module.css')
? '[folder]'
: '[name]';
// Create a hash based on a the file location and class name. Will be unique
// across a project, and close to globally unique.
const hash = loaderUtils.getHashDigest(context.resourcePath + localName, 'md5', 'base64', 5);
// Use loaderUtils to find the file or folder name
const className = loaderUtils.interpolateName(
context,
`${fileNameOrFolder}_${localName}__${hash}`,
options
);
// remove the .module that appears in every classname when based on the file.
return className.replace('.module_', '_');
};
/* eslint-disable import/no-extraneous-dependencies, prefer-destructuring */
const path = require('path');
const webpack = require('webpack');
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const CircularDependencyPlugin = require('circular-dependency-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
// const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
// const OfflinePlugin = require('offline-plugin');
const getCSSModuleLocalIdent = require('./getCSSModuleLocalIdent');
const getClientEnvironment = require('./env');
const paths = require('./paths');
// Webpack uses `publicPath` to determine where the app is being served from.
// In development, we always serve from the root. This makes config easier.
const publicPath = '/';
// `publicUrl` is just like `publicPath`, but we will provide it to our app
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
// Omit trailing slash as %PUBLIC_PATH%/xyz looks better than %PUBLIC_PATH%xyz.
const publicUrl = '';
// Get environment variables to inject into our app.
const env = getClientEnvironment(publicUrl);
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
// const SharedCache = {};
const getCacheLoader = () => ({
loader: require.resolve('cache-loader'),
options: {
cacheDirectory: path.join(paths.buildCache, 'cache-loader')
}
});
// const getThreadLoader = () => ({
// loader: require.resolve('thread-loader'),
// options: {
// poolTimeout: Infinity
// }
// });
// common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
getCacheLoader(),
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: cssOptions
} // ,
// {
// // Options for PostCSS as we reference these options twice
// // Adds vendor prefixing based on your specified browser support in
// // package.json
// loader: require.resolve('postcss-loader'),
// options: {
// // Necessary for external CSS imports to work
// // https://github.com/facebook/create-react-app/issues/2677
// ident: 'postcss',
// plugins: () => [
// require('postcss-flexbugs-fixes'),
// autoprefixer({
// flexbox: 'no-2009'
// })
// ]
// }
// }
];
if (preProcessor) {
loaders.push(require.resolve(preProcessor));
}
return loaders;
};
// This is the development configuration.
// It is focused on developer experience and fast rebuilds.
// The production configuration is different and lives in a separate file.
module.exports = {
mode: 'development',
// cache: SharedCache,
// You may want 'eval' instead if you prefer to see the compiled output in DevTools.
// See the discussion in https://github.com/facebook/create-react-app/issues/343.
devtool: 'cheap-module-source-map',
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
entry: [
// We ship a few polyfills by default:
require.resolve('./polyfills'),
require.resolve('webpack-dev-server/client') + '?/', // eslint-disable-line
require.resolve('webpack/hot/dev-server'),
paths.appIndexJs
// We include the app code last so that if there is a runtime error during
// initialization, it doesn't blow up the WebpackDevServer client, and
// changing JS code would still trigger a refresh.
],
output: {
// Add /* filename */ comments to generated require()s in the output.
pathinfo: false,
// This does not produce a real file. It's just the virtual path that is
// served by WebpackDevServer in development. This is the JS bundle
// containing code from all our entry points, and the Webpack runtime.
filename: 'static/js/bundle.js',
// There are also additional JS chunk files if you use code splitting.
chunkFilename: 'static/js/[name].chunk.js',
// This is the URL that app is served from. We use "/" in development.
publicPath,
// Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')
},
optimization: {
splitChunks: false,
runtimeChunk: true,
removeAvailableModules: false,
removeEmptyChunks: false
},
resolve: {
// This allows you to set a fallback for where Webpack should look for modules.
// We placed these paths second because we want `node_modules` to "win"
// if there are any conflicts. This matches Node resolution mechanism.
// https://github.com/facebook/create-react-app/issues/253
modules: ['node_modules'].concat(
// It is guaranteed to exist because we tweak it in `env.js`
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
),
// These are the reasonable defaults supported by the Node ecosystem.
// We also include JSX as a common component filename extension to support
// some tools, although we do not recommend using it, see:
// https://github.com/facebook/create-react-app/issues/290
// `web` extension prefixes have been added for better support
// for React Native Web.
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
// alias: {
// // Support React Native Web
// // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
// 'react-native': 'react-native-web'
// },
// plugins: [
// // Prevents users from importing files from outside of src/ (or node_modules/).
// // This often causes confusion because we only process files within src/ with babel.
// // To fix this, we prevent you from importing files out of src/ -- if you'd like to,
// // please link the files into your node_modules/ and let module-resolution kick in.
// // Make sure your source files are compiled, as they will not be processed in any way.
// // new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
// ],
unsafeCache: true,
cacheWithContext: true
},
module: {
strictExportPresence: true,
rules: [
// // Disable require.ensure as it's not a standard language feature.
// {
// parser: {
// requireEnsure: false
// }
// },
// // First, run the linter.
// // It's important to do this before Babel processes the JS.
// {
// test: /\.(js|jsx|mjs)$/,
// enforce: 'pre',
// use: [
// {
// options: {
// // formatter: eslintFormatter,
// eslintPath: require.resolve('eslint'),
// baseConfig: {
// extends: [require.resolve('@cognistreamer/eslint-config')]
// }
// },
// loader: require.resolve('eslint-loader')
// }
// ],
// include: paths.srcPaths,
// exclude: [/[/\\\\]node_modules[/\\\\]/]
// },
{
// "oneOf" will traverse all following loaders until one will
// match the requirements. When no loader matches it will fall
// back to the "file" loader at the end of the loader list.
oneOf: [
// "url" loader works like "file" loader except that it embeds assets
// smaller than specified limit in bytes as data URLs to avoid requests.
// A missing `test` is equivalent to a match.
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
use: [
getCacheLoader(),
{
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]'
}
}
]
},
// Process application JS with Babel.
{
test: /\.(js|jsx|mjs)$/,
include: paths.srcPaths,
exclude: /node_modules/,
use: [
{
loader: require.resolve('babel-loader'),
options: {
babelrc: false,
cacheDirectory: path.join(paths.buildCache, 'babel-loader'),
presets: [
require.resolve('./babel-preset-react-app')
]
}
}
]
},
// Process any JS outside of the app with Babel.
// Unlike the application JS, we only compile the standard ES features.
// {
// test: /\.js$/,
// use: [
// getCacheLoader(),
// {
// loader: require.resolve('babel-loader'),
// options: {
// babelrc: false,
// compact: false,
// presets: [
// require.resolve('./babel-preset-react-app-dependencies')
// ],
// cacheDirectory: true,
// highlightCode: true
// }
// }
// ]
// },
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
// In production, we use a plugin to extract that CSS to a file, but
// in development "style" loader enables hot editing of CSS.
// By default we support CSS Modules with the extension .module.css
{
test: cssRegex,
exclude: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 0
})
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 0,
modules: true,
getLocalIdent: getCSSModuleLocalIdent
})
},
// Opt-in support for SASS (using .scss or .sass extensions).
// Chains the sass-loader with the css-loader and the style-loader
// to immediately apply all styles to the DOM.
// By default we support SASS Modules with the
// extensions .module.scss or .module.sass
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders({ importLoaders: 1 }, 'fast-sass-loader')
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
test: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 1,
modules: true,
getLocalIdent: getCSSModuleLocalIdent
},
'fast-sass-loader'
)
},
// The GraphQL loader preprocesses GraphQL queries in .graphql files.
{
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
use: [
getCacheLoader(),
{
loader: 'graphql-tag/loader'
}
]
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.
// This loader doesn't use a "test" so it will catch all modules
// that fall through the other loaders.
{
// Exclude `js` files to keep "css" loader working as it injects
// its runtime that would otherwise be processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/, /\.flow$/],
use: [
getCacheLoader(),
{
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]'
}
}
]
}
]
}
// ** STOP ** Are you adding a new loader?
// Make sure to add the new loader(s) before the "file" loader.
]
},
plugins: [
// Generates an `index.html` file with the <script> injected.
new webpack.debug.ProfilingPlugin(),
new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml
}),
new CircularDependencyPlugin({
// exclude detection of files based on a RegExp
exclude: /a\.js|node_modules/,
// add errors to webpack instead of warnings
failOnError: true
}),
// Makes some environment variables available in index.html.
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
// In development, this will be an empty string.
// new InterpolateHtmlPlugin(env.raw),
// Makes some environment variables available to the JS code, for example:
// if (process.env.NODE_ENV === 'development') { ... }. See `./env.js`.
new webpack.DefinePlugin(env.stringified),
// This is necessary to emit hot updates (currently CSS only):
new webpack.HotModuleReplacementPlugin(),
// Watcher doesn't work well if you mistype casing in a path so we use
// a plugin that prints an error when you attempt to do this.
// See https://github.com/facebook/create-react-app/issues/240
// new CaseSensitivePathsPlugin(),
// If you require a missing module and then `npm install` it, you still have
// to restart the development server for Webpack to discover it. This plugin
// makes the discovery automatic so you don't have to restart.
// See https://github.com/facebook/create-react-app/issues/186
// new WatchMissingNodeModulesPlugin(paths.appNodeModules),
// Moment.js is an extremely popular library that bundles large locale files
// by default due to how Webpack interprets its code. This is a practical
// solution that requires the user to opt into importing specific locales.
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new webpack.ContextReplacementPlugin(/graphql-language-service-interface[\\/]dist$/, new RegExp('^\\./.*\\.js$'))
],
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
node: {
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
},
// Turn off performance hints during development because we don't do any
// splitting or minification in interest of speed. These warnings become
// cumbersome.
// https://github.com/facebook/create-react-app/pull/4077#discussion_r178082927
performance: false
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment