@shopify/loom-plugin-build-library-extended
This package is a compliment to @shopify/loom-plugin-build-library
. It enhances the build provided by @shopify/loom-plugin-build-library
, teaching Rollup and Jest about additional file types. It provides support for parsing styles (.scss
files), images (.svg
, .jpg
, .png
files) and graphql (.graphql
files). In also provdes type generation for graphql files.
It exposes two plugins - buildLibraryExtended
and buildLibraryExtendedWorkspace
that should be added to your loom plugins after the buildLibrary
and buildLibraryWorkspace
plugins provided by @shopify/loom-plugin-build-library
.
Installation
$ yarn add @shopify/loom-plugin-build-library-extended --dev
Usage
Add buildLibraryExtended
and buildLibraryExtendedWorkspace
to your loom plugins.
import {createPackage, Runtime} from '@shopify/loom';
import {
buildLibrary,
buildLibraryWorkspace,
} from '@shopify/loom-plugin-build-library';
import {
buildLibraryExtended,
buildLibraryExtendedWorkspace,
} from '@shopify/loom-plugin-build-library-extended';
export default createPackage((pkg) => {
pkg.entry({root: './src/index.js'});
pkg.use(
buildLibrary({
targets: 'defaults, node 12.22',
commonjs: true,
esmodules: true,
esnext: true,
}),
buildLibraryWorkspace(),
buildLibraryExtended({
// Optional. Defaults to false. Defines if graphql files should be processed.
graphql: false,
}),
buildLibraryExtendedWorkspace({
// Optional. Defaults to false. Defines if d.ts files should be generated for graphql files.
graphql: false,
// Optional. Defaults to `{}`. Defines any overrides for typescript generation, such as exportFormat and customScalars.
// See https://github.com/Shopify/quilt/blob/main/packages/graphql-typescript-definitions/README.md#node
generateGraphqlOptions: {},
}),
);
});
Styles
.scss
files shall be processed using dart-sass
, PostCSS
and postcss-modules
. @shopify/postcss-plugin
is used to apply autoprefixing of vendor prefixes and other style transforms.
Create scss files and import them into your JS/TS files. Each style file will expose a default export that is an object containing classnames defined in your style file.
// component.scss
.MyStyle {
color: red;
}
.MySecondStyle {
color: blue;
}
// component.tsx
import styles from './component.scss';
export function Component() {
return (
<>
<div className={styles.MyStyle}>I am red</div>
<div className={styles.MySecondStyle}>I am blue</div>
</>
);
}
Currently plain .css
files are not supported.
In esmodules
builds a styles.css
file shall be created at in build/esm/styles.css
containing all your scss files concatenated in the order of import. Consuming applications must import this style file. Currently creating a css file per input entrypoint is not supported.
In esnext
builds a .css
file will be created per .scss
file in your source and imports to scss files are placed with imports to the .css
file. This allows consumers that understand esnext builds to only include the styles for the components it uses, instead of having to load the styles for all components.
Images
.svg
, .png
and .jpg
expose a default export that is a base64 representation of the image. This value can then be used as the src
attribute of img
tags. This is good for small images but is an inefficient way of handling larger image. This functionality is provided by @rollup/plugin-image
.
// component.tsx
import myImage from './images/my-image.svg';
export function Component() {
return <img src={myImage} alt="" />;
}
An exception to this is svg files inside an icons
folder, which shall expose the svg represented as a React component. This allows the image to be rendered as a React component, or passed into @shopify/polaris
's Icon
component. This functionality is provided by @svgr/rollup
.
// component.tsx
import {Icon} from '@shopify/polaris';
import MyIcon from './icons/my-icon.svg';
export function Component() {
return (
<>
<MyIcon />
<Icon source={MyIcon} />
</>
);
}
GraphQL
.graphql
files expose a default export that is the query provided by the file. This functionality is provided by @rollup/plugin-graphql
.
# bookList.graphql
query BookList {
books {
id
title
genre
}
}
// component.tsx
import {useQuery} from '@shopify/react-graphql';
import bookList from './myQuery.graphql';
export function Component() {
const {data, error, loading} = useQuery(bookList);
return JSON.stringify({data, error, loading});
}
When you call buildLibraryExtendedWorkspace({graphql: true})
.d.ts
files shall be generated for all graphql files as part of your pre-build and type-check steps using graphql-typescript-definitions
. This exposes type exports of GraphQL data shapes. For instance in the above example bookList.graphql
shall expose a BookListQuery
interface. This requires the presense of a .graphqlconfig
file that references your schema. See graphql-typescript-definitions
's readme for more information on how to configure this.
Generate graphql types that enable type inferrence with Apollo 3's hooks
By default graphql-typescript-definitions
generates types that enable type inferrence in the hooks provided by @shopify/react-graphql
and other quilt-based packages. If you want to use Apollo 3's hooks instead, you must adjust the exportFormat
option.
If you need types that work with both @graphql-typed-document-node/core
(used by Apollo 3) and graphql-typed
(used by @shopify/react-graphql
and other quilt-based packages) use ExportFormat.DocumentWithTypedDocumentNode
. You only need Apollo 3 support use ExportFormat.TypedDocumentNode
. You must be using at least graphql-typescript-definitions
v3.3.0 to use these value.
import {createPackage, Runtime} from '@shopify/loom';
import {
buildLibrary,
buildLibraryWorkspace,
} from '@shopify/loom-plugin-build-library';
import {
buildLibraryExtended,
buildLibraryExtendedWorkspace,
} from '@shopify/loom-plugin-build-library-extended';
import {ExportFormat} from 'graphql-typescript-definitions';
export default createPackage((pkg) => {
pkg.entry({root: './src/index.js'});
pkg.use(
buildLibrary({
targets: 'defaults, node 12.22',
commonjs: true,
esmodules: true,
esnext: true,
}),
buildLibraryWorkspace(),
buildLibraryExtended({graphql: true}),
buildLibraryExtendedWorkspace({
graphql: true,
generateGraphqlOptions: {
exportFormat: ExportFormat.DocumentWithTypedDocumentNode,
},
}),
);
});
Overriding PostCSS config
We provide an initial PostCSS config that supports autoprefixing, using @shopify/postcss-plugin
. If you need to adjust this config, you can call the postcss()
plugin after buildLibraryExtended
to override the defaults.
import {createPackage} from '@shopify/loom';
import {
buildLibrary,
buildLibraryWorkspace,
} from '@shopify/loom-plugin-build-library';
import {
buildLibraryExtended,
buildLibraryExtendedWorkspace,
postcss,
} from '@shopify/loom-plugin-build-library-extended';
import {myPostcssPlugin} from 'my-postcss-plugin';
export default createPackage((pkg) => {
pkg.entry({root: './src/index.js'});
pkg.use(
buildLibrary({targets: 'node 12.22.0', commonjs: true}),
buildLibraryWorkspace(),
buildLibraryExtended(),
buildLibraryExtendedWorkspace(),
// Override initial postcss options.
// Return a new object, instead of mutating the argument object.
postcss({
config(postcssConfig) {
return {
...postcssConfig,
plugins: [...(postcssConfig.plugins || []), myPostcssPlugin()],
};
},
}),
);
});