2018-10-30 18:57:48 +00:00
/ * *
* External dependencies
* /
2018-11-06 21:53:22 +00:00
const { get } = require ( 'lodash' ) ;
const path = require ( 'path' ) ;
2024-09-05 00:14:32 +00:00
const fs = require ( 'fs' ) ;
2018-11-15 18:16:23 +00:00
const CopyWebpackPlugin = require ( 'copy-webpack-plugin' ) ;
2021-08-19 14:15:59 +00:00
const CustomTemplatedPathPlugin = require ( '@wordpress/custom-templated-path-webpack-plugin' ) ;
2023-07-13 00:12:03 +00:00
const BundleAnalyzerPlugin =
require ( 'webpack-bundle-analyzer' ) . BundleAnalyzerPlugin ;
2020-04-29 18:01:27 +00:00
const MomentTimezoneDataPlugin = require ( 'moment-timezone-data-webpack-plugin' ) ;
2022-04-21 05:18:24 +00:00
const ForkTsCheckerWebpackPlugin = require ( 'fork-ts-checker-webpack-plugin' ) ;
2023-03-16 03:52:03 +00:00
const ReactRefreshWebpackPlugin = require ( '@pmmmwh/react-refresh-webpack-plugin' ) ;
2018-11-06 21:53:22 +00:00
/ * *
2021-08-19 14:15:59 +00:00
* Internal dependencies
2018-11-06 21:53:22 +00:00
* /
2021-08-19 14:15:59 +00:00
const UnminifyWebpackPlugin = require ( './unminify' ) ;
2022-06-07 13:35:04 +00:00
const {
webpackConfig : styleConfig ,
} = require ( '@woocommerce/internal-style-build' ) ;
2022-03-18 21:53:19 +00:00
const WooCommerceDependencyExtractionWebpackPlugin = require ( '../../packages/js/dependency-extraction-webpack-plugin/src/index' ) ;
2018-11-06 21:53:22 +00:00
2018-07-23 20:14:40 +00:00
const NODE _ENV = process . env . NODE _ENV || 'development' ;
2020-06-22 12:38:17 +00:00
const WC _ADMIN _PHASE = process . env . WC _ADMIN _PHASE || 'development' ;
2023-03-17 09:52:24 +00:00
const isHot = Boolean ( process . env . HOT ) ;
2023-03-16 03:52:03 +00:00
const isProduction = NODE _ENV === 'production' ;
2018-04-17 21:38:56 +00:00
2024-09-05 00:14:32 +00:00
const getSubdirectoriesAt = ( searchPath ) => {
const dir = path . resolve ( searchPath ) ;
return fs
. readdirSync ( dir , { withFileTypes : true } )
. filter ( ( entry ) => entry . isDirectory ( ) )
. map ( ( entry ) => entry . name ) ;
} ;
const WC _ADMIN _PACKAGES _DIR = '../../packages/js' ;
const WP _ADMIN _SCRIPTS _DIR = './client/wp-admin-scripts' ;
// wpAdminScripts are loaded on wp-admin pages outside the context of WooCommerce Admin
// See ./client/wp-admin-scripts/README.md for more details
const wpAdminScripts = getSubdirectoriesAt ( WP _ADMIN _SCRIPTS _DIR ) ; // automatically include all subdirs
2018-11-15 18:16:23 +00:00
const wcAdminPackages = [
2024-09-05 00:14:32 +00:00
// we use a whitelist for this instead of dynamically generating it because not all folders are packages meant for consumption
2023-03-10 14:58:02 +00:00
'admin-layout' ,
2018-11-15 18:16:23 +00:00
'components' ,
'csv-export' ,
'currency' ,
2020-10-30 06:52:52 +00:00
'customer-effort-score' ,
2018-11-15 18:16:23 +00:00
'date' ,
2021-04-16 03:34:15 +00:00
'experimental' ,
'explat' ,
2018-11-15 18:16:23 +00:00
'navigation' ,
2022-06-03 23:05:26 +00:00
'notices' ,
2019-01-29 16:48:46 +00:00
'number' ,
2020-03-25 03:20:17 +00:00
'data' ,
2020-08-20 04:59:52 +00:00
'tracks' ,
2021-05-28 23:26:38 +00:00
'onboarding' ,
2023-09-27 20:38:56 +00:00
'block-templates' ,
2023-01-31 13:38:28 +00:00
'product-editor' ,
2024-08-02 02:25:39 +00:00
'remote-logging' ,
2018-11-15 18:16:23 +00:00
] ;
2024-09-05 00:14:32 +00:00
2022-04-12 07:29:50 +00:00
const getEntryPoints = ( ) => {
const entryPoints = {
app : './client/index.js' ,
} ;
wcAdminPackages . forEach ( ( name ) => {
2024-09-05 00:14:32 +00:00
entryPoints [ name ] = ` ${ WC _ADMIN _PACKAGES _DIR } / ${ name } ` ;
2022-04-12 07:29:50 +00:00
} ) ;
wpAdminScripts . forEach ( ( name ) => {
2024-09-05 00:14:32 +00:00
entryPoints [ name ] = ` ${ WP _ADMIN _SCRIPTS _DIR } / ${ name } ` ;
2022-04-12 07:29:50 +00:00
} ) ;
return entryPoints ;
} ;
2019-10-21 18:13:25 +00:00
2022-04-15 04:08:59 +00:00
// WordPress.org’ s translation infrastructure ignores files named “.min.js” so we need to name our JS files without min when releasing the plugin.
2022-04-12 07:29:50 +00:00
const outputSuffix = WC _ADMIN _PHASE === 'core' ? '' : '.min' ;
2020-09-15 15:36:58 +00:00
2024-08-01 21:15:10 +00:00
// Here we are patching a dependency, see https://github.com/woocommerce/woocommerce/pull/45548 for more details.
// Should be revisited: using the dependency patching, but seems we need some codebase tweaks as it uses xstate 4/5 mix.
require ( 'fs-extra' ) . ensureSymlinkSync (
path . join ( _ _dirname , './node_modules/xstate5' ) ,
path . join ( _ _dirname , './node_modules/@xstate5/react/node_modules/xstate' )
) ;
2018-04-17 21:38:56 +00:00
const webpackConfig = {
mode : NODE _ENV ,
2022-04-12 07:29:50 +00:00
entry : getEntryPoints ( ) ,
2018-04-17 21:38:56 +00:00
output : {
2019-10-21 18:13:25 +00:00
filename : ( data ) => {
2022-04-12 06:47:03 +00:00
// Output wpAdminScripts to wp-admin-scripts folder
// See https://github.com/woocommerce/woocommerce-admin/pull/3061
2020-02-14 02:23:21 +00:00
return wpAdminScripts . includes ( data . chunk . name )
2022-04-12 07:29:50 +00:00
? ` wp-admin-scripts/[name] ${ outputSuffix } .js `
: ` [name]/index ${ outputSuffix } .js ` ;
2019-10-21 18:13:25 +00:00
} ,
2024-02-27 08:07:53 +00:00
chunkFilename : ` chunks/[name] ${ outputSuffix } .js?ver=[contenthash] ` ,
2023-11-16 19:13:36 +00:00
path : path . join ( _ _dirname , '/build' ) ,
2022-04-12 07:29:50 +00:00
library : {
// Expose the exports of entry points so we can consume the libraries in window.wc.[modulename] with WooCommerceDependencyExtractionWebpackPlugin.
name : [ 'wc' , '[modulename]' ] ,
type : 'window' ,
} ,
2022-04-12 06:47:03 +00:00
// A unique name of the webpack build to avoid multiple webpack runtimes to conflict when using globals.
2022-03-18 10:59:05 +00:00
uniqueName : '__wcAdmin_webpackJsonp' ,
2018-04-17 21:38:56 +00:00
} ,
module : {
2023-03-27 01:42:33 +00:00
parser : styleConfig . parser ,
2018-04-17 21:38:56 +00:00
rules : [
2018-12-06 22:08:40 +00:00
{
2022-04-12 07:29:50 +00:00
test : /\.(t|j)sx?$/ ,
2018-12-06 22:08:40 +00:00
parser : {
2022-04-12 06:47:03 +00:00
// Disable AMD to fix an issue where underscore and lodash where clashing
// See https://github.com/woocommerce/woocommerce-admin/pull/1004 and https://github.com/Automattic/woocommerce-services/pull/1522
2018-12-06 22:08:40 +00:00
amd : false ,
} ,
2022-02-21 02:34:25 +00:00
exclude : [
2024-07-29 13:20:17 +00:00
/[\/\\]node_modules[\/\\]\.pnpm[\/\\]/ ,
/[\/\\](changelog|bin|build|docs|test)[\/\\]/ ,
2022-02-21 02:34:25 +00:00
] ,
2018-12-26 02:46:32 +00:00
use : {
loader : 'babel-loader' ,
options : {
2021-02-24 01:24:22 +00:00
presets : [
'@wordpress/babel-preset-default' ,
[
'@babel/preset-env' ,
{
2022-04-12 06:47:03 +00:00
// Add polyfills such as Array.flat based on their usage in the code
// See https://github.com/woocommerce/woocommerce-admin/pull/6411/
2021-02-24 01:24:22 +00:00
corejs : '3' ,
useBuiltIns : 'usage' ,
} ,
] ,
2021-03-01 03:01:22 +00:00
[ '@babel/preset-typescript' ] ,
2021-02-24 01:24:22 +00:00
] ,
2023-03-16 03:52:03 +00:00
plugins : [
'@babel/plugin-proposal-class-properties' ,
! isProduction &&
2023-03-17 09:52:24 +00:00
isHot &&
2023-03-16 03:52:03 +00:00
require . resolve ( 'react-refresh/babel' ) ,
] . filter ( Boolean ) ,
2024-07-19 07:40:01 +00:00
cacheDirectory : path . resolve (
_ _dirname ,
'../../node_modules/.cache/babel-loader'
) ,
cacheCompression : false ,
2018-12-26 02:46:32 +00:00
} ,
} ,
} ,
2018-09-24 15:36:35 +00:00
{ test : /\.md$/ , use : 'raw-loader' } ,
2019-05-28 14:05:55 +00:00
{
test : /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/ ,
2022-09-13 09:40:56 +00:00
type : 'asset' ,
2019-05-28 14:05:55 +00:00
} ,
2021-08-19 14:15:59 +00:00
... styleConfig . rules ,
2018-04-17 21:38:56 +00:00
] ,
} ,
2018-05-10 16:35:46 +00:00
resolve : {
2022-04-12 06:47:03 +00:00
fallback : {
// Reduce bundle size by omitting Node crypto library.
// See https://github.com/woocommerce/woocommerce-admin/pull/5768
crypto : 'empty' ,
2022-06-08 09:16:31 +00:00
// Ignore fs, path to skip resolve errors for @automattic/calypso-config
fs : false ,
path : false ,
2022-03-18 10:59:05 +00:00
} ,
2021-03-01 03:01:22 +00:00
extensions : [ '.json' , '.js' , '.jsx' , '.ts' , '.tsx' ] ,
2018-07-20 03:40:15 +00:00
alias : {
2021-03-10 15:11:37 +00:00
'~' : path . resolve ( _ _dirname + '/client' ) ,
2024-08-30 16:27:10 +00:00
'react/jsx-dev-runtime' : require . resolve ( 'react/jsx-dev-runtime' ) ,
'react/jsx-runtime' : require . resolve ( 'react/jsx-runtime' ) ,
2018-07-20 03:40:15 +00:00
} ,
2018-05-10 16:35:46 +00:00
} ,
2018-10-30 18:57:48 +00:00
plugins : [
2021-08-19 14:15:59 +00:00
... styleConfig . plugins ,
2022-04-12 06:47:03 +00:00
// Runs TypeScript type checker on a separate process.
2022-04-27 21:54:54 +00:00
! process . env . STORYBOOK && new ForkTsCheckerWebpackPlugin ( ) ,
2018-11-06 21:53:22 +00:00
new CustomTemplatedPathPlugin ( {
modulename ( outputPath , data ) {
const entryName = get ( data , [ 'chunk' , 'name' ] ) ;
if ( entryName ) {
2022-04-12 06:47:03 +00:00
// Convert the dash-case name to a camel case module name.
// For example, 'csv-export' -> 'csvExport'
2020-02-14 02:23:21 +00:00
return entryName . replace ( /-([a-z])/g , ( match , letter ) =>
letter . toUpperCase ( )
) ;
2018-11-06 21:53:22 +00:00
}
return outputPath ;
} ,
} ) ,
2022-04-12 06:47:03 +00:00
// The package build process doesn't handle extracting CSS from JS files, so we copy them separately.
new CopyWebpackPlugin ( {
2022-03-18 10:59:05 +00:00
patterns : wcAdminPackages . map ( ( packageName ) => ( {
2024-02-27 08:07:53 +00:00
// Copy css and style.asset.php files.
from : ` ../../packages/js/ ${ packageName } /build-style/*.{css,php} ` ,
2022-03-18 10:59:05 +00:00
to : ` ./ ${ packageName } /[name][ext] ` ,
2022-04-12 06:47:03 +00:00
noErrorOnMissing : true ,
2022-06-09 02:45:36 +00:00
// Overwrites files already in compilation.assets to ensure we use the assets from the build-style.
// This is required for @woocommerce/component to use @automattic/* packages because scss styles from @automattic/* packages will be automatically generated by mini-css-extract-plugin with the same output name.
force : true ,
2022-04-12 06:47:03 +00:00
} ) ) ,
} ) ,
2023-03-31 17:36:40 +00:00
// Get all product editor blocks so they can be loaded via JSON.
new CopyWebpackPlugin ( {
patterns : [
{
from : '../../packages/js/product-editor/build/blocks' ,
to : './product-editor/blocks' ,
} ,
] ,
} ) ,
2023-03-16 03:52:03 +00:00
// React Fast Refresh.
2023-03-17 09:52:24 +00:00
! isProduction && isHot && new ReactRefreshWebpackPlugin ( ) ,
2021-06-02 03:54:00 +00:00
// We reuse this Webpack setup for Storybook, where we need to disable dependency extraction.
! process . env . STORYBOOK &&
2022-04-28 09:22:27 +00:00
new WooCommerceDependencyExtractionWebpackPlugin ( {
requestToExternal ( request ) {
if ( request === '@wordpress/components/build/ui' ) {
// The external wp.components does not include ui components, so we need to skip requesting to external here.
return null ;
}
2023-08-28 01:28:05 +00:00
2024-08-30 16:27:10 +00:00
if ( request . startsWith ( '@wordpress/dataviews' ) ) {
return null ;
}
2023-08-28 01:28:05 +00:00
if ( request . startsWith ( '@wordpress/edit-site' ) ) {
// The external wp.editSite does not include edit-site components, so we need to skip requesting to external here. We can remove this once the edit-site components are exported in the external wp.editSite.
// We use the edit-site components in the customize store.
return null ;
}
2022-04-28 09:22:27 +00:00
} ,
} ) ,
2022-04-12 06:47:03 +00:00
// Reduces data for moment-timezone.
2020-04-29 18:01:27 +00:00
new MomentTimezoneDataPlugin ( {
2022-04-12 06:47:03 +00:00
// This strips out timezone data before the year 2000 to make a smaller file.
startYear : 2000 ,
2020-04-29 18:01:27 +00:00
} ) ,
process . env . ANALYZE && new BundleAnalyzerPlugin ( ) ,
2022-04-15 04:08:59 +00:00
// We only want to generate unminified files in the development phase.
WC _ADMIN _PHASE === 'development' &&
// Generate unminified files to load the unminified version when `define( 'SCRIPT_DEBUG', true );` is set in wp-config.
2020-07-28 02:32:58 +00:00
new UnminifyWebpackPlugin ( {
test : /\.js($|\?)/i ,
mainEntry : 'app/index.min.js' ,
} ) ,
2020-04-29 18:01:27 +00:00
] . filter ( Boolean ) ,
optimization : {
minimize : NODE _ENV !== 'development' ,
2020-10-06 12:58:15 +00:00
splitChunks : {
2022-04-12 06:47:03 +00:00
// Not to generate chunk names because it caused a stressful workflow when deploying the plugin to WP.org
// See https://github.com/woocommerce/woocommerce-admin/pull/5229
name : false ,
} ,
2020-12-02 01:17:02 +00:00
} ,
2018-04-17 21:38:56 +00:00
} ;
2023-03-16 03:52:03 +00:00
if ( ! isProduction || WC _ADMIN _PHASE === 'development' ) {
// Set default sourcemap mode if it wasn't set by WP_DEVTOOL.
webpackConfig . devtool = webpackConfig . devtool || 'source-map' ;
2023-03-17 09:52:24 +00:00
if ( isHot ) {
// Add dev server config
// Copied from https://github.com/WordPress/gutenberg/blob/05bea6dd5c6198b0287c41a401d36a06b48831eb/packages/scripts/config/webpack.config.js#L312-L326
webpackConfig . devServer = {
devMiddleware : {
writeToDisk : true ,
} ,
allowedHosts : 'auto' ,
host : 'localhost' ,
port : 8887 ,
proxy : {
'/build' : {
pathRewrite : {
'^/build' : '' ,
} ,
2023-03-16 03:52:03 +00:00
} ,
} ,
2023-03-17 09:52:24 +00:00
} ;
}
2018-04-17 23:51:48 +00:00
}
2018-04-17 21:38:56 +00:00
module . exports = webpackConfig ;