Add tree shaking support for woocommerce components (https://github.com/woocommerce/woocommerce-admin/pull/7034)

* Add woocommerce/components tree shaking support

* Compile individual component styles for individual use

* Update readme

* Add changelog

* Fix correct import

* Update readme with dependency extraction updates

* Update dependency extraction naming
This commit is contained in:
louwie17 2021-05-26 16:35:46 -03:00 committed by GitHub
parent dc175824c9
commit 69dfdf733c
16 changed files with 158 additions and 84 deletions

View File

@ -115,7 +115,7 @@ function buildJsFile( file, silent ) {
*/
async function buildPackageScss( packagePath ) {
const srcDir = path.resolve( packagePath, SRC_DIR );
const scssFiles = glob.sync( `${ srcDir }/*.scss` );
const scssFiles = glob.sync( `${ srcDir }/**/*.scss` );
// Build scss files individually.
return Promise.all( scssFiles.map( ( file ) => buildScssFile( file ) ) );

View File

@ -2,6 +2,7 @@
- Fix style regression with the Chart header. #7002
- Remove the use of Dashicons and replace with @wordpress/icons or gridicons #7020
- Add tree shaking support to this package. #7034
# 6.2.0

View File

@ -11,3 +11,24 @@ npm install @woocommerce/components --save
```
View [the full Component documentation](https://woocommerce.github.io/woocommerce-admin/#/components/) for usage information.
## Usage
```jsx
/**
* Woocommerce dependencies
*/
import { Card } from '@woocommerce/components';
export default function MyCard() {
return (
<Card title="Store Performance" description="Key performance metrics">
<p>Your stuff in a Card.</p>
</Card>
);
}
```
Many components include CSS to add style, you will need to add in order to appear correctly. Within WooCommerce, add the `wc-components` stylesheet as a dependency of your plugin's stylesheet. See [wp_enqueue_style documentation](https://developer.wordpress.org/reference/functions/wp_enqueue_style/#parameters) for how to specify dependencies.
In non-WordPress projects, link to the `build-style/card/style.css` file directly, it is located at `node_modules/@woocommerce/components/build-style/<component_name>/style.css`.

View File

@ -20,6 +20,10 @@
"main": "build/index.js",
"module": "build-module/index.js",
"react-native": "src/index",
"sideEffects": [
"build-style/**",
"src/**/*.scss"
],
"dependencies": {
"@woocommerce/csv-export": "file:../csv-export",
"@woocommerce/currency": "file:../currency",

View File

@ -10,7 +10,8 @@ import { isArray, isNumber, isString } from 'lodash';
* @param {Array<string|Node>} components array of components
*
* @return {string} concatenated text content of all nodes
*/ export function textContent( components ) {
*/
export function textContent( components ) {
let text = '';
const toText = ( component ) => {

View File

@ -13,6 +13,8 @@ import PropTypes from 'prop-types';
import { withViewportMatch } from '@wordpress/viewport';
import { validateDateInputForRange } from '@woocommerce/date';
import 'react-dates/initialize';
// ^^ The above: Turn on react-dates classes/styles, see https://github.com/airbnb/react-dates#initialize.
/**
* Internal dependencies

View File

@ -1,9 +1,3 @@
/**
* External dependencies
*/
import 'react-dates/initialize';
// The above: Turn on react-dates classes/styles, see https://github.com/airbnb/react-dates#initialize
export { default as AdvancedFilters } from './advanced-filters';
export { default as AnimationSlider } from './animation-slider';
export { default as Chart } from './chart';

View File

@ -9,7 +9,7 @@ import PropTypes from 'prop-types';
* Internal dependencies
*/
import EllipsisMenu from '../ellipsis-menu';
import { H } from '../section';
import { H } from '../section/header';
import { validateComponent } from '../lib/proptype-validator';
/**

View File

@ -0,0 +1,13 @@
/**
* External dependencies
*/
import { createContext } from '@wordpress/element';
/**
* Context container for heading level. We start at 2 because the `h1` is defined in <Header />
*
* See https://medium.com/@Heydon/managing-heading-levels-in-design-systems-18be9a746fa3
*/
const Level = createContext( 2 );
export { Level };

View File

@ -0,0 +1,24 @@
/**
* External dependencies
*/
import { useContext } from '@wordpress/element';
/**
* Internal dependencies
*/
import { Level } from './context';
/**
* These components are used to frame out the page content for accessible heading hierarchy. Instead of defining fixed heading levels
* (`h2`, `h3`, ) you can use `<H />` to create "section headings", which look to the parent `<Section />`s for the appropriate
* heading level.
*
* @param {Object} props -
* @return {Object} -
*/
export function H( props ) {
const level = useContext( Level );
const Heading = 'h' + Math.min( level, 6 );
return <Heading { ...props } />;
}

View File

@ -1,72 +1,2 @@
/**
* External dependencies
*/
import { createContext } from '@wordpress/element';
import PropTypes from 'prop-types';
/**
* Context container for heading level. We start at 2 because the `h1` is defined in <Header />
*
* See https://medium.com/@Heydon/managing-heading-levels-in-design-systems-18be9a746fa3
*/
const Level = createContext( 2 );
/**
* These components are used to frame out the page content for accessible heading hierarchy. Instead of defining fixed heading levels
* (`h2`, `h3`, ) you can use `<H />` to create "section headings", which look to the parent `<Section />`s for the appropriate
* heading level.
*
* @param {Object} props -
* @return {Object} -
*/
export function H( props ) {
return (
<Level.Consumer>
{ ( level ) => {
const Heading = 'h' + Math.min( level, 6 );
return <Heading { ...props } />;
} }
</Level.Consumer>
);
}
/**
* The section wrapper, used to indicate a sub-section (and change the header level context).
*
* @param {Object} props
* @param {string} props.component
* @param {Node} props.children
* @return {Object} -
*/
export function Section( { component, children, ...props } ) {
const Component = component || 'div';
return (
<Level.Consumer>
{ ( level ) => (
<Level.Provider value={ level + 1 }>
{ component === false ? (
children
) : (
<Component { ...props }>{ children }</Component>
) }
</Level.Provider>
) }
</Level.Consumer>
);
}
Section.propTypes = {
/**
* The wrapper component for this section. Optional, defaults to `div`. If passed false, no wrapper is used. Additional props
* passed to Section are passed on to the component.
*/
component: PropTypes.oneOfType( [
PropTypes.func,
PropTypes.string,
PropTypes.bool,
] ),
/**
* The children inside this section, rendered in the `component`. This increases the context level for the next heading used.
*/
children: PropTypes.node,
};
export { Section } from './section';
export { H } from './header';

View File

@ -0,0 +1,50 @@
/**
* External dependencies
*/
import PropTypes from 'prop-types';
/**
* Internal dependencies
*/
import { Level } from './context';
/**
* The section wrapper, used to indicate a sub-section (and change the header level context).
*
* @param {Object} props
* @param {string} props.component
* @param {Node} props.children
* @return {Object} -
*/
export function Section( { component, children, ...props } ) {
const Component = component || 'div';
return (
<Level.Consumer>
{ ( level ) => (
<Level.Provider value={ level + 1 }>
{ component === false ? (
children
) : (
<Component { ...props }>{ children }</Component>
) }
</Level.Provider>
) }
</Level.Consumer>
);
}
Section.propTypes = {
/**
* The wrapper component for this section. Optional, defaults to `div`. If passed false, no wrapper is used. Additional props
* passed to Section are passed on to the component.
*/
component: PropTypes.oneOfType( [
PropTypes.func,
PropTypes.string,
PropTypes.bool,
] ),
/**
* The children inside this section, rendered in the `component`. This increases the context level for the next heading used.
*/
children: PropTypes.node,
};

View File

@ -1,3 +1,7 @@
# Unreleased
- Add new `bundledPackages` option to bundle in specific packages.
# 1.5.0
- Add `@woocommerce/explat` to list of packages.

View File

@ -33,3 +33,26 @@ Additional module requests on top of Wordpress [Dependency Extraction Webpack Pl
| `@woocommerce/blocks-registry` | `wc['wcBlocksRegistry']` | `wc-blocks-registry` |
| `@woocommerce/settings` | `wc['wcSettings']` | `wc-settings` |
| `@woocommerce/*` | `wc['*']` | `wc-*` |
#### Options
An object can be passed to the constructor to customize the behavior, for example:
```js
module.exports = {
plugins: [
new WooCommerceDependencyExtractionWebpackPlugin( {
bundledPackages: [ '@woocommerce/components' ],
} ),
],
};
```
##### `bundledPackages`
- Type: array
- Default: []
A list of potential WooCommerce excluded packages, this will include the excluded package within the bundle (example above).
For more supported options see the original [dependency extraction plugin](https://github.com/WordPress/gutenberg/blob/trunk/packages/dependency-extraction-webpack-plugin/README.md#options).

View File

@ -17,7 +17,7 @@ function camelCaseDash( string ) {
return string.replace( /-([a-z])/g, ( _, letter ) => letter.toUpperCase() );
}
const wooRequestToExternal = ( request ) => {
const wooRequestToExternal = ( request, excludedExternals ) => {
if ( packages.includes( request ) ) {
const handle = request.substring( WOOCOMMERCE_NAMESPACE.length );
const irregularExternalMap = {
@ -25,6 +25,10 @@ const wooRequestToExternal = ( request ) => {
settings: [ 'wc', 'wcSettings' ],
};
if ( ( excludedExternals || [] ).includes( request ) ) {
return;
}
if ( irregularExternalMap[ handle ] ) {
return irregularExternalMap[ handle ];
}
@ -63,7 +67,10 @@ class DependencyExtractionWebpackPlugin extends WPDependencyExtractionWebpackPlu
typeof externalRequest === 'undefined' &&
this.options.useDefaults
) {
externalRequest = wooRequestToExternal( request );
externalRequest = wooRequestToExternal(
request,
this.options.bundledPackages || []
);
}
if ( externalRequest ) {

View File

@ -119,7 +119,7 @@ const webpackConfig = {
},
{
test: /\.s?css$/,
exclude: /storybook\/wordpress/,
exclude: [ /storybook\/wordpress/, /build-style\/*\/*.css/ ],
use: [
MiniCssExtractPlugin.loader,
'css-loader',