1 | const path = require('path')
|
2 | const esbuild = require('esbuild')
|
3 | const { getOptions } = require('loader-utils')
|
4 |
|
5 |
|
6 | let service
|
7 |
|
8 | const exts = ['.js', '.jsx', '.ts', '.tsx']
|
9 |
|
10 | module.exports = async function (source) {
|
11 | const done = this.async()
|
12 | const options = getOptions(this)
|
13 | if (!service) {
|
14 | return done(
|
15 | new Error(
|
16 | `[esbuild-loader] You need to add ESBuildPlugin to your webpack config first`
|
17 | )
|
18 | )
|
19 | }
|
20 |
|
21 | try {
|
22 | const ext = path.extname(this.resourcePath)
|
23 | if (!exts.includes(ext)) {
|
24 | return done(
|
25 | new Error(`[esbuild-loader] Unsupported file extension: ${ext}`)
|
26 | )
|
27 | }
|
28 |
|
29 | const result = await service.transform(source, {
|
30 | target: options.target || 'es2015',
|
31 | loader: ext.slice(1),
|
32 | jsxFactory: options.jsxFactory,
|
33 | jsxFragment: options.jsxFragment,
|
34 | sourcemap: options.sourceMap
|
35 | })
|
36 | done(null, result.js, result.jsSourceMap)
|
37 | } catch (err) {
|
38 | done(err)
|
39 | }
|
40 | }
|
41 |
|
42 | module.exports.ESBuildPlugin = class ESBuildPlugin {
|
43 | |
44 |
|
45 |
|
46 | apply(compiler) {
|
47 | let watching = false
|
48 |
|
49 | const startService = async () => {
|
50 | if (!service) {
|
51 | service = await esbuild.startService()
|
52 | }
|
53 | }
|
54 |
|
55 | compiler.hooks.run.tapPromise('esbuild', async () => {
|
56 | await startService()
|
57 | })
|
58 | compiler.hooks.watchRun.tapPromise('esbuild', async () => {
|
59 | watching = true
|
60 | await startService()
|
61 | })
|
62 |
|
63 | compiler.hooks.done.tap('esbuild', () => {
|
64 | if (!watching && service) {
|
65 | service.stop()
|
66 | service = undefined
|
67 | }
|
68 | })
|
69 | }
|
70 | }
|