1 | # `typescript-plugin-styled-components`
|
2 |
|
3 | This is a TypeScript transformer that improves development experience of [`styled-components`](https://www.styled-components.com/).
|
4 |
|
5 | The 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 |
|
7 | The 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 |
|
9 | If 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 |
|
11 | Note: 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 |
|
15 | The 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 |
|
35 | This section describes how to integrate the plugin into the build/bundling process driven by [**Webpack**](https://webpack.js.org/) and its TypeScript loaders.
|
36 |
|
37 | There 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 |
|
42 | Both loaders use the same setting `getCustomTransformers` which is an optional function that returns `{ before?: Transformer[], after?: Transformer[] }`.
|
43 | In order to inject the transformer into compilation, add it to `before` transformers array, like: `{ before: [styledComponentsTransformer] }`.
|
44 |
|
45 | ## `awesome-typescript-loader`
|
46 |
|
47 | In 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
|
51 | const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default;
|
52 |
|
53 | // 2. create a transformer;
|
54 | // the factory additionally accepts an options object which described below
|
55 | const styledComponentsTransformer = createStyledComponentsTransformer();
|
56 |
|
57 | // 3. add getCustomTransformer method to the loader config
|
58 | var 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 |
|
76 | Please 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.
|
77 | To solve this please refer to [Forked process configuration](#forked-process-configuration) section.
|
78 |
|
79 | ## `ts-loader`
|
80 |
|
81 | In 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
|
85 | const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default;
|
86 |
|
87 | // 2. create a transformer;
|
88 | // the factory additionally accepts an options object which described below
|
89 | const styledComponentsTransformer = createStyledComponentsTransformer();
|
90 |
|
91 | // 3. add getCustomTransformer method to the loader config
|
92 | var 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 |
|
110 | Please 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.
|
111 | To solve this please refer to [Forked process configuration](#forked-process-configuration) section.
|
112 |
|
113 | ## Forked process configuration
|
114 |
|
115 | To 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 |
|
119 | Let'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
|
122 | const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default;
|
123 |
|
124 | // 2. create a transformer;
|
125 | // the factory additionally accepts an options object which described below
|
126 | const styledComponentsTransformer = createStyledComponentsTransformer();
|
127 |
|
128 | // 3. create getCustomTransformer function
|
129 | const getCustomTransformers = () => ({ before: [styledComponentsTransformer] });
|
130 |
|
131 | // 4. export getCustomTransformers
|
132 | module.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 |
|
141 | options: {
|
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 |
|
150 | This 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 |
|
152 | In 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
|
156 | const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default;
|
157 |
|
158 | // 2. create a transformer;
|
159 | // the factory additionally accepts an options object which described below
|
160 | const styledComponentsTransformer = createStyledComponentsTransformer();
|
161 |
|
162 | // 3. add getCustomTransformer method to the loader config
|
163 | var 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 |
|
182 | TypeScript command line compiler tool (`tsc`) does not support using of pluggable modules and transformers.
|
183 | For that reason there are other tools created that do support pluggable transformers. See [`ttypescript` compiler](#ttypescript-compiler) section.
|
184 |
|
185 | # `ttypescript` compiler
|
186 |
|
187 | The [`ttypescript` compiler](https://github.com/cevek/ttypescript) is a CLI tool that allows to use TypeScript compiler with pluggable transformers.
|
188 | To 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
|
212 | function createTransformer(options?: Partial<Options>): TransformerFactory<SourceFile>;
|
213 | ```
|
214 |
|
215 | A factory that creates an instance of a TypeScript transformer (which is a factory itself).
|
216 |
|
217 | It allows to optionally pass options that allow to tweak transformer's behavior. See `Options` for details.
|
218 |
|
219 | ## `Options`
|
220 |
|
221 | ```ts
|
222 | interface 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 |
|
234 | This 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 |
|
240 | Default strategy is to use `bindingName` if it's defined and use inference algorithm from `filename` otherwise.
|
241 |
|
242 | Sample:
|
243 | ```js
|
244 | function getStyledComponentDisplay(filename, bindingName) {
|
245 | return bindingName || makePascalCase(filename);
|
246 | }
|
247 | ```
|
248 |
|
249 | ### `ssr`
|
250 |
|
251 | By adding a unique identifier to every styled component, this plugin avoids checksum mismatches
|
252 | due to different class generation on the client and on the server.
|
253 |
|
254 | This option allows to disable component id generation by setting it to `false`.
|
255 |
|
256 | Default value is `true` which means that component id is being injected.
|
257 |
|
258 | ### `displayName`
|
259 |
|
260 | This option enhances the attached CSS class name on each component with richer output
|
261 | to help identify your components in the DOM without React DevTools.
|
262 |
|
263 | It also adds allows you to see the component's `displayName` in React DevTools.
|
264 |
|
265 | To disable `displayName` generation set this option to `false`
|
266 |
|
267 | Default value is `true` which means that display name is being injected.
|
268 |
|
269 | ### `minify`
|
270 |
|
271 | The option allows to turn on minification of inline styles used in styled components.
|
272 | It is similar to [`babel-plugin-styled-components`](https://github.com/styled-components/babel-plugin-styled-components)'s same option.
|
273 | The 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 |
|
277 | Default value is `false` which means the minification is not being performed.
|
278 |
|
279 | ### `componentIdPrefix`
|
280 |
|
281 | To 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 |
|
283 | Default value is `''` which means that no namespacing will happen.
|
284 |
|
285 | ### `identifiers`
|
286 |
|
287 | This 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
|
293 | interface 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 |
|
310 | Example
|
311 |
|
312 | ```ts
|
313 | const styledComponentsTransformer = createStyledComponentsTransformer({
|
314 | identifiers: {
|
315 | styled: ['styled', 'typedStyled'] // typedStyled is an additional identifier of styled API
|
316 | }
|
317 | });
|
318 | ```
|
319 |
|
320 | # Notes
|
321 |
|
322 | Technically, `typescript-plugin-styled-components` is not a TypeScript plugin, since it is only exposed as a TypeScript transformer.
|