Skip to content

Commit 431c8d6

Browse files
authoredJul 14, 2023
feat(swc-loader): Move to monorepo (swc-project#2)
1 parent dc33ec2 commit 431c8d6

25 files changed

+1800
-0
lines changed
 

‎.editorconfig

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# EditorConfig is awesome: http://EditorConfig.org
2+
root = true
3+
4+
# Unix-style newlines with a newline ending every file
5+
[*]
6+
end_of_line = lf
7+
insert_final_newline = true
8+
charset = utf-8
9+
indent_style = space
10+
indent_size = 4

‎packages/swc-loader/.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules/
2+
build/
3+
package-lock.json
4+
*.log

‎packages/swc-loader/.npmignore

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.vscode
2+
node_modules/
3+
example/
4+
package-lock.json
5+
*.log
6+
yarn.lock
7+
example-config/
8+
example-src-dir/
9+
example-sync/

‎packages/swc-loader/LICENSE

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Copyright (c) 2017 The swc Project Developers
2+
3+
Permission is hereby granted, free of charge, to any
4+
person obtaining a copy of this software and associated
5+
documentation files (the "Software"), to deal in the
6+
Software without restriction, including without
7+
limitation the rights to use, copy, modify, merge,
8+
publish, distribute, sublicense, and/or sell copies of
9+
the Software, and to permit persons to whom the Software
10+
is furnished to do so, subject to the following
11+
conditions:
12+
13+
The above copyright notice and this permission notice
14+
shall be included in all copies or substantial portions
15+
of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18+
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19+
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20+
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21+
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24+
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25+
DEALINGS IN THE SOFTWARE.

‎packages/swc-loader/README.md

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# swc-loader
2+
3+
This package allows transpiling JavaScript files using swc and webpack.
4+
5+
## Installation
6+
7+
```sh
8+
npm i --save-dev @swc/core swc-loader webpack
9+
```
10+
11+
## Usage
12+
13+
```js
14+
module: {
15+
rules: [
16+
{
17+
test: /\.m?js$/,
18+
exclude: /(node_modules|bower_components)/,
19+
use: {
20+
// Use `.swcrc` to configure swc
21+
loader: "swc-loader"
22+
}
23+
}
24+
];
25+
}
26+
```
27+
28+
You can pass options to the loader by using the option property.
29+
30+
```js
31+
module: {
32+
rules: [
33+
{
34+
test: /\.ts$/,
35+
exclude: /(node_modules|bower_components)/,
36+
use: {
37+
loader: "swc-loader",
38+
options: {
39+
jsc: {
40+
parser: {
41+
syntax: "typescript"
42+
}
43+
}
44+
}
45+
}
46+
}
47+
];
48+
}
49+
```
50+
51+
If you get an error while using `swc-loader`, you can pass `sync: true` to get correct error message.
52+
53+
```js
54+
module: {
55+
rules: [
56+
{
57+
test: /\.ts$/,
58+
exclude: /(node_modules|bower_components)/,
59+
use: {
60+
loader: "swc-loader",
61+
options: {
62+
// This makes swc-loader invoke swc synchronously.
63+
sync: true,
64+
jsc: {
65+
parser: {
66+
syntax: "typescript"
67+
}
68+
}
69+
}
70+
}
71+
}
72+
];
73+
}
74+
```
75+
76+
## Configuration Reference
77+
Refer https://swc.rs/docs/configuring-swc
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "example",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"license": "MIT",
6+
"scripts": {
7+
"build": "webpack && cp public/* build",
8+
"start": "ecstatic build --port 3000"
9+
},
10+
"dependencies": {
11+
"react": "^17.0.2",
12+
"react-dom": "^17.0.2"
13+
},
14+
"devDependencies": {
15+
"ecstatic": "^3.3.0",
16+
"webpack": "^5.69.1",
17+
"webpack-cli": "^4.9.2"
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>swc-loader example</title>
5+
<script src="/bundle.js" async defer></script>
6+
</head>
7+
<body>
8+
<div id="root"></div>
9+
</body>
10+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from "react";
2+
import ReactDOM from "react-dom";
3+
4+
function App() {
5+
return <h1>JSX is working!</h1>;
6+
}
7+
8+
ReactDOM.render(<App />, document.getElementById("root"));
9+
if (foo !== "foo") {
10+
throw new Error("foo is not foo");
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"use strict";
2+
3+
const path = require("path");
4+
5+
module.exports = {
6+
mode: "development",
7+
entry: path.join(__dirname, "src", "index.js"),
8+
output: {
9+
path: path.join(__dirname, "build"),
10+
filename: "bundle.js",
11+
},
12+
module: {
13+
rules: [
14+
{
15+
test: /\.js$/,
16+
exclude: /(node_modules|bower_components)/,
17+
use: {
18+
loader: require.resolve(".."), // you would put swc-loader
19+
options: {
20+
jsc: {
21+
target: "es2015",
22+
parser: {
23+
syntax: "ecmascript",
24+
jsx: true,
25+
dynamicImport: true,
26+
classProperty: true,
27+
exportNamespaceFrom: true,
28+
exportDefaultFrom: true,
29+
},
30+
},
31+
},
32+
},
33+
},
34+
],
35+
},
36+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "example",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"license": "MIT",
6+
"scripts": {
7+
"build": "webpack && cp public/* build",
8+
"start": "ecstatic build --port 3000"
9+
},
10+
"dependencies": {
11+
"react": "^17.0.2",
12+
"react-dom": "^17.0.2"
13+
},
14+
"devDependencies": {
15+
"ecstatic": "^3.3.0",
16+
"webpack": "^5.69.1",
17+
"webpack-cli": "^4.9.2"
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>swc-loader example</title>
5+
<script src="/bundle.js" async defer></script>
6+
</head>
7+
<body>
8+
<div id="root"></div>
9+
</body>
10+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from "react";
2+
import ReactDOM from "react-dom";
3+
4+
function App() {
5+
return <h1>JSX is working!</h1>;
6+
}
7+
8+
ReactDOM.render(<App />, document.getElementById("root"));
9+
if (foo !== "foo") {
10+
throw new Error("foo is not foo");
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"use strict";
2+
3+
const path = require("path");
4+
5+
module.exports = {
6+
mode: "development",
7+
devtool: "source-map",
8+
entry: path.join(__dirname, "src", "index.js"),
9+
output: {
10+
path: path.join(__dirname, "build"),
11+
filename: "bundle.js",
12+
},
13+
module: {
14+
rules: [
15+
{
16+
test: /\.js$/,
17+
exclude: /(node_modules|bower_components)/,
18+
use: {
19+
loader: require.resolve(".."), // you would put swc-loader
20+
options: {
21+
jsc: {
22+
parser: {
23+
syntax: "ecmascript",
24+
jsx: true,
25+
},
26+
transform: {
27+
react: {
28+
pragma: "React.createElement",
29+
pragmaFrag: "React.Fragment",
30+
throwIfNamespace: true,
31+
development: false,
32+
useBuiltins: false,
33+
},
34+
},
35+
},
36+
},
37+
},
38+
},
39+
],
40+
},
41+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import React from "react";
2+
import ReactDOM from "react-dom";
3+
4+
function App() {
5+
return <h1>JSX is working!</h1>;
6+
}
7+
8+
ReactDOM.render(<App />, document.getElementById("root"));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "example",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"license": "MIT",
6+
"scripts": {
7+
"build": "webpack && cp public/* build",
8+
"start": "ecstatic build --port 3000"
9+
},
10+
"dependencies": {
11+
"react": "^17.0.2",
12+
"react-dom": "^17.0.2"
13+
},
14+
"devDependencies": {
15+
"ecstatic": "^3.3.0",
16+
"webpack": "^5.69.1",
17+
"webpack-cli": "^4.9.2"
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>swc-loader example</title>
5+
<script src="/bundle.js" async defer></script>
6+
</head>
7+
<body>
8+
<div id="root"></div>
9+
</body>
10+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"use strict";
2+
3+
const path = require("path");
4+
5+
module.exports = {
6+
mode: "development",
7+
entry: path.join(__dirname, "index.js"),
8+
output: {
9+
path: path.join(__dirname, "build"),
10+
filename: "bundle.js",
11+
},
12+
module: {
13+
rules: [
14+
{
15+
test: /\.js$/,
16+
exclude: /(node_modules|bower_components)/,
17+
use: {
18+
loader: require.resolve(".."), // you would put swc-loader
19+
options: {
20+
sync: true,
21+
jsc: {
22+
parser: {
23+
syntax: "ecmascript",
24+
jsx: true,
25+
},
26+
transform: {
27+
react: {
28+
pragma: "React.createElement",
29+
pragmaFrag: "React.Fragment",
30+
throwIfNamespace: true,
31+
development: false,
32+
useBuiltins: false,
33+
},
34+
},
35+
},
36+
},
37+
},
38+
},
39+
],
40+
},
41+
};

‎packages/swc-loader/example/index.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import React from "react";
2+
import ReactDOM from "react-dom";
3+
4+
function App() {
5+
return <h1>JSX is working!</h1>;
6+
}
7+
8+
ReactDOM.render(<App />, document.getElementById("root"));
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "example",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"license": "MIT",
6+
"scripts": {
7+
"build": "webpack && cp public/* build",
8+
"start": "ecstatic build --port 3000"
9+
},
10+
"dependencies": {
11+
"react": "^17.0.2",
12+
"react-dom": "^17.0.2"
13+
},
14+
"devDependencies": {
15+
"ecstatic": "^3.3.0",
16+
"webpack": "^5.69.1",
17+
"webpack-cli": "^4.9.2"
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>swc-loader example</title>
5+
<script src="/bundle.js" async defer></script>
6+
</head>
7+
<body>
8+
<div id="root"></div>
9+
</body>
10+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"use strict";
2+
3+
const path = require("path");
4+
5+
module.exports = {
6+
mode: "development",
7+
// Enable source map
8+
devtool: "source-map",
9+
entry: path.join(__dirname, "index.js"),
10+
output: {
11+
path: path.join(__dirname, "build"),
12+
filename: "bundle.js",
13+
},
14+
module: {
15+
rules: [
16+
{
17+
test: /\.js$/,
18+
exclude: /(node_modules|bower_components)/,
19+
use: {
20+
loader: require.resolve(".."), // you would put swc-loader
21+
options: {
22+
// Enable source map
23+
sourceMap: true,
24+
jsc: {
25+
parser: {
26+
syntax: "ecmascript",
27+
jsx: true,
28+
},
29+
transform: {
30+
react: {
31+
pragma: "React.createElement",
32+
pragmaFrag: "React.Fragment",
33+
throwIfNamespace: true,
34+
development: false,
35+
useBuiltins: false,
36+
},
37+
},
38+
},
39+
},
40+
},
41+
},
42+
],
43+
},
44+
};

‎packages/swc-loader/package.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "swc-loader",
3+
"version": "0.2.3",
4+
"description": "Webpack plugin for swc",
5+
"main": "src/index.js",
6+
"repository": "https://github.com/swc-project/swc-loader",
7+
"author": "강동윤 <kdy1997.dev@gmail.com>",
8+
"license": "MIT",
9+
"private": false,
10+
"devDependencies": {
11+
"@swc/core": "^1.2.147",
12+
"webpack": "^5.69.1"
13+
},
14+
"peerDependencies": {
15+
"@swc/core": "^1.2.147",
16+
"webpack": ">=2"
17+
}
18+
}

‎packages/swc-loader/src/index.js

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
const swc = require("@swc/core");
2+
3+
function makeLoader() {
4+
return function (source, inputSourceMap) {
5+
// Make the loader async
6+
const callback = this.async();
7+
const filename = this.resourcePath;
8+
9+
let loaderOptions =
10+
(typeof this.getOptions === "function"
11+
? this.getOptions()
12+
: require("loader-utils").getOptions(this)) || {};
13+
14+
// Standardize on 'sourceMaps' as the key passed through to Webpack, so that
15+
// users may safely use either one alongside our default use of
16+
// 'this.sourceMap' below without getting error about conflicting aliases.
17+
if (
18+
Object.prototype.hasOwnProperty.call(loaderOptions, "sourceMap") &&
19+
!Object.prototype.hasOwnProperty.call(loaderOptions, "sourceMaps")
20+
) {
21+
loaderOptions = Object.assign({}, loaderOptions, {
22+
sourceMaps: loaderOptions.sourceMap,
23+
});
24+
delete loaderOptions.sourceMap;
25+
}
26+
27+
if (inputSourceMap && typeof inputSourceMap === "object") {
28+
inputSourceMap = JSON.stringify(inputSourceMap);
29+
}
30+
31+
const programmaticOptions = Object.assign({}, loaderOptions, {
32+
filename,
33+
inputSourceMap: inputSourceMap || undefined,
34+
35+
// Set the default sourcemap behavior based on Webpack's mapping flag,
36+
// but allow users to override if they want.
37+
sourceMaps:
38+
loaderOptions.sourceMaps === undefined
39+
? this.sourceMap
40+
: loaderOptions.sourceMaps,
41+
42+
// Ensure that Webpack will get a full absolute path in the sourcemap
43+
// so that it can properly map the module back to its internal cached
44+
// modules.
45+
sourceFileName: filename,
46+
});
47+
if (!programmaticOptions.inputSourceMap) {
48+
delete programmaticOptions.inputSourceMap;
49+
}
50+
51+
const sync = programmaticOptions.sync;
52+
const parseMap = programmaticOptions.parseMap;
53+
54+
// Remove loader related options
55+
delete programmaticOptions.sync;
56+
delete programmaticOptions.parseMap;
57+
delete programmaticOptions.customize;
58+
delete programmaticOptions.cacheDirectory;
59+
delete programmaticOptions.cacheIdentifier;
60+
delete programmaticOptions.cacheCompression;
61+
delete programmaticOptions.metadataSubscribers;
62+
63+
// auto detect development mode
64+
if (
65+
this.mode &&
66+
programmaticOptions.jsc &&
67+
programmaticOptions.jsc.transform &&
68+
programmaticOptions.jsc.transform.react &&
69+
!Object.prototype.hasOwnProperty.call(
70+
programmaticOptions.jsc.transform.react,
71+
"development"
72+
)
73+
) {
74+
programmaticOptions.jsc.transform.react.development =
75+
this.mode === "development";
76+
}
77+
78+
if (programmaticOptions.sourceMaps === "inline") {
79+
// Babel has this weird behavior where if you set "inline", we
80+
// inline the sourcemap, and set 'result.map = null'. This results
81+
// in bad behavior from Babel since the maps get put into the code,
82+
// which Webpack does not expect, and because the map we return to
83+
// Webpack is null, which is also bad. To avoid that, we override the
84+
// behavior here so "inline" just behaves like 'true'.
85+
programmaticOptions.sourceMaps = true;
86+
}
87+
88+
try {
89+
if (sync) {
90+
const output = swc.transformSync(source, programmaticOptions);
91+
callback(
92+
null,
93+
output.code,
94+
parseMap ? JSON.parse(output.map) : output.map
95+
);
96+
} else {
97+
swc.transform(source, programmaticOptions).then(
98+
(output) => {
99+
callback(
100+
null,
101+
output.code,
102+
parseMap ? JSON.parse(output.map) : output.map
103+
);
104+
},
105+
(err) => {
106+
callback(err);
107+
}
108+
);
109+
}
110+
} catch (e) {
111+
callback(e);
112+
}
113+
};
114+
}
115+
116+
module.exports = makeLoader();
117+
module.exports.custom = makeLoader;

‎packages/swc-loader/yarn.lock

+573
Large diffs are not rendered by default.

‎pnpm-lock.yaml

+651
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
Please sign in to comment.