UNPKG

12.9 kBMarkdownView Raw
1# `typescript-plugin-styled-components`
2
3This is a TypeScript transformer that improves development experience of [`styled-components`](https://www.styled-components.com/).
4
5The main purpose is to provide compile-time information of creates styled components, such as names of these components, for the run-time, allowing to operate with proper names of such the components.
6
7The plugin was mostly inspired by great Babel's plugin [`babel-plugin-styled-components`](https://github.com/styled-components/babel-plugin-styled-components) and partially provides similar functionality for TypeScript users.
8
9If you like it, consider [![Buy me a coffee](https://www.buymeacoffee.com/assets/img/custom_images/yellow_img.png)](https://www.buymeacoffee.com/igorbek)
10
11Note: This transformer will be useful to you only when you are transpiling your TS code using actual TS compiler, like `tsc` `ts-loader` or `awesome-typescript-loader`. If your TS code is transpiled using [`babel-plugin-transform-typescript`](https://babeljs.io/docs/en/babel-plugin-transform-typescript), you should use [`babel-plugin-styled-components`](https://github.com/styled-components/babel-plugin-styled-components) instead.
12
13# Installation
14
15The following command adds the packages to the project as a development-time dependency:
16
17<pre><code><strong>yarn</strong> add <em>typescript-plugin-styled-components</em> --dev</code></pre>
18
19# Documentation
20
21- [Integration with `Webpack`](#Integration-with-Webpack)
22 - [`awesome-typescript-loader`](#awesome-typescript-loader)
23 - [`ts-loader`](#ts-loader)
24 - [Forked process configuration](#Forked-process-configuration)
25- [Integration with `Rollup`](#Integration-with-Rollup)
26- [TypeScript compiler (CLI)](#TypeScript-compiler-CLI)
27- [`ttypescript` compiler](#ttypescript-compiler)
28- [API](#API)
29 - [`createTransformer`](#createTransformer)
30 - [`Options`](#Options)
31- [Notes](#Notes)
32
33# Integration with `Webpack`
34
35This section describes how to integrate the plugin into the build/bundling process driven by [**Webpack**](https://webpack.js.org/) and its TypeScript loaders.
36
37There are two popular TypeScript loaders that support specifying custom transformers:
38
39- [**awesome-typescript-loader**](https://github.com/s-panferov/awesome-typescript-loader), supports custom transformers since v3.1.3
40- [**ts-loader**](https://github.com/TypeStrong/ts-loader), supports custom transformers since v2.2.0
41
42Both loaders use the same setting `getCustomTransformers` which is an optional function that returns `{ before?: Transformer[], after?: Transformer[] }`.
43In order to inject the transformer into compilation, add it to `before` transformers array, like: `{ before: [styledComponentsTransformer] }`.
44
45## `awesome-typescript-loader`
46
47In the `webpack.config.js` file in the section where **awesome-typescript-loader** is configured as a loader:
48
49```js
50// 1. import default from the plugin module
51const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default;
52
53// 2. create a transformer;
54// the factory additionally accepts an options object which described below
55const styledComponentsTransformer = createStyledComponentsTransformer();
56
57// 3. add getCustomTransformer method to the loader config
58var config = {
59 ...
60 module: {
61 rules: [
62 {
63 test: /\.tsx?$/,
64 loader: 'awesome-typescript-loader',
65 options: {
66 ... // other loader's options
67 getCustomTransformers: () => ({ before: [styledComponentsTransformer] })
68 }
69 }
70 ]
71 }
72 ...
73};
74```
75
76Please note, that in the development mode, `awesome-typescript-loader` uses multiple separate processes to speed up compilation. In that mode the above configuration cannot work because functions, which `getCustomTransformers` is, are not transferrable between processes.
77To solve this please refer to [Forked process configuration](#forked-process-configuration) section.
78
79## `ts-loader`
80
81In the `webpack.config.js` file in the section where **ts-loader** is configured as a loader:
82
83```js
84// 1. import default from the plugin module
85const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default;
86
87// 2. create a transformer;
88// the factory additionally accepts an options object which described below
89const styledComponentsTransformer = createStyledComponentsTransformer();
90
91// 3. add getCustomTransformer method to the loader config
92var config = {
93 ...
94 module: {
95 rules: [
96 {
97 test: /\.tsx?$/,
98 loader: 'ts-loader',
99 options: {
100 ... // other loader's options
101 getCustomTransformers: () => ({ before: [styledComponentsTransformer] })
102 }
103 }
104 ]
105 }
106 ...
107};
108```
109
110Please note, when `awesome-typescript-loader` is used with `HappyPack` or `thread-loader`, they use multiple separate processes to speed up compilation. In that mode the above configuration cannot work because functions, which `getCustomTransformers` is, are not transferrable between processes.
111To solve this please refer to [Forked process configuration](#forked-process-configuration) section.
112
113## Forked process configuration
114
115To configure the transformer for development mode in `awesome-typescript-loader` or `ts-loader` with `HappyPack` or `thread-loader`, you need to make `getCustomTransformers` a resolvable module name instead of the function. Since the configuration is very similar, here's an example:
116
117### 1. Move `styledComponentsTransformer` into a separate file
118
119Let's assume it is in the same folder as your `webpack.config` and has name `webpack.ts-transformers.js`:
120```js
121// 1. import default from the plugin module
122const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default;
123
124// 2. create a transformer;
125// the factory additionally accepts an options object which described below
126const styledComponentsTransformer = createStyledComponentsTransformer();
127
128// 3. create getCustomTransformer function
129const getCustomTransformers = () => ({ before: [styledComponentsTransformer] });
130
131// 4. export getCustomTransformers
132module.exports = getCustomTransformers;
133```
134
135### 2. Change the loader's options to point to that file instead of explicit function
136
137```diff
138-const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default;
139-const styledComponentsTransformer = createStyledComponentsTransformer();
140
141options: {
142 ... // other loader's options
143- getCustomTransformers: () => ({ before: [styledComponentsTransformer] })
144+ getCustomTransformers: path.join(__dirname, './webpack.ts-transformers.js')
145}
146```
147
148# Integration with `Rollup`
149
150This section describes how to integrate the plugin into the build/bundling process driven by [**Rollup**](https://rollupjs.org/guide/en/) and its TypeScript loader - [**rollup-plugin-typescript2**](https://github.com/Igorbek/typescript-plugin-styled-components).
151
152In the `rollup.config.js` file in the section where **rollup-plugin-typescript2** is configured as a loader:
153
154```js
155// 1. import default from the plugin module
156const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default;
157
158// 2. create a transformer;
159// the factory additionally accepts an options object which described below
160const styledComponentsTransformer = createStyledComponentsTransformer();
161
162// 3. add getCustomTransformer method to the loader config
163var config = {
164 ...
165 plugins: [
166 rollupTypescript({
167 ...
168 transformers: [
169 () => ({
170 before: [styledComponentsTransformer],
171 }),
172 ],
173 }),
174 ...
175 ],
176 ...
177};
178```
179
180# TypeScript compiler (CLI)
181
182TypeScript command line compiler tool (`tsc`) does not support using of pluggable modules and transformers.
183For that reason there are other tools created that do support pluggable transformers. See [`ttypescript` compiler](#ttypescript-compiler) section.
184
185# `ttypescript` compiler
186
187The [`ttypescript` compiler](https://github.com/cevek/ttypescript) is a CLI tool that allows to use TypeScript compiler with pluggable transformers.
188To use the transformer with that tool you can configure it by updating `tsconfig.json` the following way:
189
190```js
191{
192 "compilerOptions": {
193 "plugins": [
194 {
195 "transform": "typescript-plugin-styled-components",
196 "type": "config",
197
198 // other typescript-plugin-styled-components options can be added here
199 "minify": true,
200 "ssr": true
201 }
202 ]
203 }
204}
205```
206
207# API
208
209## `createTransformer`
210
211```ts
212function createTransformer(options?: Partial<Options>): TransformerFactory<SourceFile>;
213```
214
215A factory that creates an instance of a TypeScript transformer (which is a factory itself).
216
217It allows to optionally pass options that allow to tweak transformer's behavior. See `Options` for details.
218
219## `Options`
220
221```ts
222interface Options {
223 getDisplayName(filename: string, bindingName: string | undefined): string | undefined;
224 identifiers: CustomStyledIdentifiers;
225 ssr: boolean;
226 displayName: boolean;
227 minify: boolean;
228 componentIdPrefix: string;
229}
230```
231
232### `getDisplayName`
233
234This method is used to determine component display name from filename and its binding name.
235
236`filename` is the file name, relative to the project base directory, of the file where the styled component defined.
237
238`bindingName` is the name that is used in the source code to bind the component. It can be `null` if the component was not bound or assigned.
239
240Default strategy is to use `bindingName` if it's defined and use inference algorithm from `filename` otherwise.
241
242Sample:
243```js
244function getStyledComponentDisplay(filename, bindingName) {
245 return bindingName || makePascalCase(filename);
246}
247```
248
249### `ssr`
250
251By adding a unique identifier to every styled component, this plugin avoids checksum mismatches
252due to different class generation on the client and on the server.
253
254This option allows to disable component id generation by setting it to `false`.
255
256Default value is `true` which means that component id is being injected.
257
258### `displayName`
259
260This option enhances the attached CSS class name on each component with richer output
261to help identify your components in the DOM without React DevTools.
262
263It also adds allows you to see the component's `displayName` in React DevTools.
264
265To disable `displayName` generation set this option to `false`
266
267Default value is `true` which means that display name is being injected.
268
269### `minify`
270
271The option allows to turn on minification of inline styles used in styled components.
272It is similar to [`babel-plugin-styled-components`](https://github.com/styled-components/babel-plugin-styled-components)'s same option.
273The minification is not exactly the same and may produce slightly different results.
274
275:warning: **Warning**: The minification is an experimental feature, please use with care.
276
277Default value is `false` which means the minification is not being performed.
278
279### `componentIdPrefix`
280
281To avoid colisions when running more than one insance of typescript-plugin-styled-components at a time, you can add a componentIdPrefix by providing an arbitrary string to this option.
282
283Default value is `''` which means that no namespacing will happen.
284
285### `identifiers`
286
287This option allows to customize identifiers used by `styled-components` API functions.
288
289> **Warning**. By providing custom identifiers, predefined ones are not added automatically.
290> Make sure you add standard APIs in case you meant to use them.
291
292```ts
293interface CustomStyledIdentifiers {
294 styled: string[];
295 attrs: string[];
296 keyframes: string[];
297 css: string[];
298 createGlobalStyle: string[];
299 extend: string[];
300}
301```
302
303- `styled` - list of identifiers of `styled` API (default `['styled']`)
304- `attrs` - list of identifiers of `attrs` API (default `['attrs']`)
305- `keyframes` - list of identifiers of `keyframes` API (default `['keyframes']`)
306- `css` - list of identifiers of `css` API (default `['css']`)
307- `createGlobalStyle` - list of identifiers of `createGlobalStyle` API (default `['createGlobalStyle']`)
308- `extend` - list of identifiers of `extend` API (default `[]`). Note this API has been deprecated in `styled-components` so starting from `1.5` this option by default has empty set, which means it does not recognize this API by default.
309
310Example
311
312```ts
313const styledComponentsTransformer = createStyledComponentsTransformer({
314 identifiers: {
315 styled: ['styled', 'typedStyled'] // typedStyled is an additional identifier of styled API
316 }
317});
318```
319
320# Notes
321
322Technically, `typescript-plugin-styled-components` is not a TypeScript plugin, since it is only exposed as a TypeScript transformer.