Skip to content

Commit e05c004

Browse files
feat: remove usage of babel for transforming SVGs
1 parent db7177b commit e05c004

File tree

9 files changed

+248
-1613
lines changed

9 files changed

+248
-1613
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ dist/
33
node_modules/
44
__mocks__/
55
__snapshots__/
6+
lib/plugins/svgr-webpack/index.js

config/webpack.dev.config.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,23 @@ module.exports = merge(commonConfig, {
115115
],
116116
},
117117
{
118+
// Use SVGR to convert SVG to React components (when used in JSX files)
118119
test: /.svg(\?v=\d+\.\d+\.\d+)?$/,
119120
issuer: /\.jsx?$/,
120-
use: ['@svgr/webpack'],
121+
use: [
122+
// Second, convert JSX to JS:
123+
{
124+
loader: 'swc-loader',
125+
options: {
126+
jsc: {
127+
parser: { syntax: 'ecmascript', jsx: true },
128+
transform: { react: { runtime: 'automatic' } },
129+
},
130+
},
131+
},
132+
// First, convert SVG to JSX:
133+
{ loader: path.resolve(__dirname, '../lib/plugins/svgr-webpack/index') },
134+
],
121135
},
122136
// Webpack, by default, uses the url-loader for images and fonts that are required/included by
123137
// files it processes, which just base64 encodes them and inlines them in the javascript

config/webpack.prod.config.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,23 @@ module.exports = merge(commonConfig, {
152152
],
153153
},
154154
{
155+
// Use SVGR to convert SVG to React components (when used in JSX files)
155156
test: /.svg(\?v=\d+\.\d+\.\d+)?$/,
156157
issuer: /\.jsx?$/,
157-
use: ['@svgr/webpack'],
158+
use: [
159+
// Second, convert JSX to JS:
160+
{
161+
loader: 'swc-loader',
162+
options: {
163+
jsc: {
164+
parser: { syntax: 'ecmascript', jsx: true },
165+
transform: { react: { runtime: 'automatic' } },
166+
},
167+
},
168+
},
169+
// First, convert SVG to JSX:
170+
{ loader: path.resolve(__dirname, '../lib/plugins/svgr-webpack/index') },
171+
],
158172
},
159173
// Webpack, by default, uses the url-loader for images and fonts that are required/included by
160174
// files it processes, which just base64 encodes them and inlines them in the javascript

lib/plugins/svgr-webpack/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Run this command to rebuild `index.js` from `index.ts`:
2+
3+
../../../node_modules/.bin/tsc -p tsconfig.json
4+
5+
If you see some error about 'prettier' not being found, you can safely ignore it.

lib/plugins/svgr-webpack/index.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"use strict";
2+
var __importDefault = (this && this.__importDefault) || function (mod) {
3+
return (mod && mod.__esModule) ? mod : { "default": mod };
4+
};
5+
Object.defineProperty(exports, "__esModule", { value: true });
6+
// Adapted from https://github.com/gregberge/svgr/blob/main/packages/webpack/src/index.ts to remove babel
7+
const util_1 = require("util");
8+
const core_1 = require("@svgr/core");
9+
const path_1 = require("path");
10+
const plugin_svgo_1 = __importDefault(require("@svgr/plugin-svgo"));
11+
const plugin_jsx_1 = __importDefault(require("@svgr/plugin-jsx"));
12+
const tranformSvg = (0, util_1.callbackify)(async (contents, options, state) => {
13+
const jsCode = await (0, core_1.transform)(contents, options, state);
14+
return jsCode;
15+
});
16+
function svgrLoader(contents) {
17+
this.cacheable?.();
18+
const callback = this.async();
19+
const options = this.getOptions();
20+
const previousExport = (() => {
21+
if (contents.startsWith('export ')) {
22+
return contents;
23+
}
24+
const exportMatches = contents.match(/^module.exports\s*=\s*(.*)/);
25+
return exportMatches ? `export default ${exportMatches[1]}` : null;
26+
})();
27+
const state = {
28+
caller: {
29+
name: 'svgr-webpack-no-babel',
30+
previousExport,
31+
defaultPlugins: [plugin_svgo_1.default, plugin_jsx_1.default],
32+
},
33+
filePath: (0, path_1.normalize)(this.resourcePath),
34+
};
35+
if (!previousExport) {
36+
tranformSvg(contents, options, state, callback);
37+
}
38+
else {
39+
this.fs.readFile(this.resourcePath, (err, result) => {
40+
if (err) {
41+
callback(err);
42+
return;
43+
}
44+
tranformSvg(String(result), options, state, (err2, content) => {
45+
if (err2) {
46+
callback(err2);
47+
return;
48+
}
49+
callback(null, content);
50+
});
51+
});
52+
}
53+
}
54+
exports.default = svgrLoader;

lib/plugins/svgr-webpack/index.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Adapted from https://github.com/gregberge/svgr/blob/main/packages/webpack/src/index.ts to remove babel
2+
import { callbackify } from 'util';
3+
import { transform, Config, State } from '@svgr/core';
4+
import { normalize } from 'path';
5+
import svgo from '@svgr/plugin-svgo';
6+
import jsx from '@svgr/plugin-jsx';
7+
import type * as webpack from 'webpack';
8+
9+
interface LoaderOptions extends Config {
10+
// babel?: boolean
11+
}
12+
13+
const tranformSvg = callbackify(
14+
async (contents: string, options: LoaderOptions, state: Partial<State>) => {
15+
const jsCode = await transform(contents, options, state);
16+
return jsCode;
17+
},
18+
);
19+
20+
function svgrLoader(
21+
this: webpack.LoaderContext<LoaderOptions>,
22+
contents: string,
23+
): void {
24+
this.cacheable?.();
25+
const callback = this.async();
26+
27+
const options = this.getOptions();
28+
29+
const previousExport = (() => {
30+
if (contents.startsWith('export ')) { return contents; }
31+
const exportMatches = contents.match(/^module.exports\s*=\s*(.*)/);
32+
return exportMatches ? `export default ${exportMatches[1]}` : null;
33+
})();
34+
35+
const state = {
36+
caller: {
37+
name: 'svgr-webpack-no-babel',
38+
previousExport,
39+
defaultPlugins: [svgo, jsx],
40+
},
41+
filePath: normalize(this.resourcePath),
42+
};
43+
44+
if (!previousExport) {
45+
tranformSvg(contents, options, state, callback);
46+
} else {
47+
this.fs.readFile(this.resourcePath, (err, result) => {
48+
if (err) {
49+
callback(err);
50+
return;
51+
}
52+
tranformSvg(String(result), options, state, (err2, content) => {
53+
if (err2) {
54+
callback(err2);
55+
return;
56+
}
57+
callback(null, content);
58+
});
59+
});
60+
}
61+
}
62+
63+
export default svgrLoader;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2022",
4+
"rootDir": ".",
5+
"outDir": ".",
6+
"moduleResolution": "Node16",
7+
"module": "Node16"
8+
},
9+
"files": ["index.ts"],
10+
"include": ["index.ts"]
11+
}

0 commit comments

Comments
 (0)