|
1 |
| -import { |
2 |
| - getDebugIdSnippet, |
3 |
| - Options, |
4 |
| - sentryUnpluginFactory, |
5 |
| - stringToUUID, |
6 |
| - SentrySDKBuildFlags, |
7 |
| - createComponentNameAnnotateHooks, |
8 |
| - Logger, |
9 |
| -} from "@sentry/bundler-plugin-core"; |
10 |
| -import * as path from "path"; |
11 |
| -import { UnpluginOptions } from "unplugin"; |
12 |
| -import { v4 as uuidv4 } from "uuid"; |
| 1 | +import { SentryWebpackPluginOptions, sentryWebpackUnpluginFactory } from "./webpack4and5"; |
13 | 2 |
|
14 | 3 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
15 | 4 | // @ts-ignore webpack is a peer dep
|
16 | 5 | import * as webpack4or5 from "webpack";
|
17 | 6 |
|
18 |
| -interface BannerPluginCallbackArg { |
19 |
| - chunk?: { |
20 |
| - hash?: string; |
21 |
| - contentHash?: { |
22 |
| - javascript?: string; |
23 |
| - }; |
24 |
| - }; |
25 |
| -} |
| 7 | +const BannerPlugin = webpack4or5?.BannerPlugin || webpack4or5?.default?.BannerPlugin; |
26 | 8 |
|
27 |
| -function webpackReleaseInjectionPlugin(injectionCode: string): UnpluginOptions { |
28 |
| - return { |
29 |
| - name: "sentry-webpack-release-injection-plugin", |
30 |
| - webpack(compiler) { |
31 |
| - // eslint-disable-next-line @typescript-eslint/ban-ts-comment |
32 |
| - // @ts-ignore webpack version compatibility shenanigans |
33 |
| - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access |
34 |
| - const BannerPlugin = |
35 |
| - // eslint-disable-next-line @typescript-eslint/ban-ts-comment |
36 |
| - // @ts-ignore webpack version compatibility shenanigans |
37 |
| - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access |
38 |
| - compiler?.webpack?.BannerPlugin || |
39 |
| - webpack4or5?.BannerPlugin || |
40 |
| - webpack4or5?.default?.BannerPlugin; |
41 |
| - compiler.options.plugins = compiler.options.plugins || []; |
42 |
| - compiler.options.plugins.push( |
43 |
| - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call |
44 |
| - new BannerPlugin({ |
45 |
| - raw: true, |
46 |
| - include: /\.(js|ts|jsx|tsx|mjs|cjs)(\?[^?]*)?(#[^#]*)?$/, |
47 |
| - banner: injectionCode, |
48 |
| - }) |
49 |
| - ); |
50 |
| - }, |
51 |
| - }; |
52 |
| -} |
| 9 | +const DefinePlugin = webpack4or5?.DefinePlugin || webpack4or5?.default?.DefinePlugin; |
53 | 10 |
|
54 |
| -function webpackComponentNameAnnotatePlugin(ignoredComponents?: string[]): UnpluginOptions { |
55 |
| - return { |
56 |
| - name: "sentry-webpack-component-name-annotate-plugin", |
57 |
| - enforce: "pre", |
58 |
| - // Webpack needs this hook for loader logic, so the plugin is not run on unsupported file types |
59 |
| - transformInclude(id) { |
60 |
| - return id.endsWith(".tsx") || id.endsWith(".jsx"); |
61 |
| - }, |
62 |
| - transform: createComponentNameAnnotateHooks(ignoredComponents).transform, |
63 |
| - }; |
64 |
| -} |
65 |
| - |
66 |
| -function webpackBundleSizeOptimizationsPlugin( |
67 |
| - replacementValues: SentrySDKBuildFlags |
68 |
| -): UnpluginOptions { |
69 |
| - return { |
70 |
| - name: "sentry-webpack-bundle-size-optimizations-plugin", |
71 |
| - webpack(compiler) { |
72 |
| - // eslint-disable-next-line @typescript-eslint/ban-ts-comment |
73 |
| - // @ts-ignore webpack version compatibility shenanigans |
74 |
| - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access |
75 |
| - const DefinePlugin = |
76 |
| - // eslint-disable-next-line @typescript-eslint/ban-ts-comment |
77 |
| - // @ts-ignore webpack version compatibility shenanigans |
78 |
| - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access |
79 |
| - compiler?.webpack?.DefinePlugin || |
80 |
| - webpack4or5?.DefinePlugin || |
81 |
| - webpack4or5?.default?.DefinePlugin; |
82 |
| - compiler.options.plugins = compiler.options.plugins || []; |
83 |
| - compiler.options.plugins.push( |
84 |
| - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call |
85 |
| - new DefinePlugin({ |
86 |
| - ...replacementValues, |
87 |
| - }) |
88 |
| - ); |
89 |
| - }, |
90 |
| - }; |
91 |
| -} |
92 |
| - |
93 |
| -function webpackDebugIdInjectionPlugin(): UnpluginOptions { |
94 |
| - return { |
95 |
| - name: "sentry-webpack-debug-id-injection-plugin", |
96 |
| - webpack(compiler) { |
97 |
| - // eslint-disable-next-line @typescript-eslint/ban-ts-comment |
98 |
| - // @ts-ignore webpack version compatibility shenanigans |
99 |
| - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access |
100 |
| - const BannerPlugin = |
101 |
| - // eslint-disable-next-line @typescript-eslint/ban-ts-comment |
102 |
| - // @ts-ignore webpack version compatibility shenanigans |
103 |
| - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access |
104 |
| - compiler?.webpack?.BannerPlugin || |
105 |
| - webpack4or5?.BannerPlugin || |
106 |
| - webpack4or5?.default?.BannerPlugin; |
107 |
| - compiler.options.plugins = compiler.options.plugins || []; |
108 |
| - compiler.options.plugins.push( |
109 |
| - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call |
110 |
| - new BannerPlugin({ |
111 |
| - raw: true, |
112 |
| - include: /\.(js|ts|jsx|tsx|mjs|cjs)(\?[^?]*)?(#[^#]*)?$/, |
113 |
| - banner: (arg?: BannerPluginCallbackArg) => { |
114 |
| - const hash = arg?.chunk?.contentHash?.javascript ?? arg?.chunk?.hash; |
115 |
| - const debugId = hash ? stringToUUID(hash) : uuidv4(); |
116 |
| - return getDebugIdSnippet(debugId); |
117 |
| - }, |
118 |
| - }) |
119 |
| - ); |
120 |
| - }, |
121 |
| - }; |
122 |
| -} |
123 |
| - |
124 |
| -function webpackDebugIdUploadPlugin( |
125 |
| - upload: (buildArtifacts: string[]) => Promise<void>, |
126 |
| - logger: Logger, |
127 |
| - forceExitOnBuildCompletion?: boolean |
128 |
| -): UnpluginOptions { |
129 |
| - const pluginName = "sentry-webpack-debug-id-upload-plugin"; |
130 |
| - return { |
131 |
| - name: pluginName, |
132 |
| - webpack(compiler) { |
133 |
| - compiler.hooks.afterEmit.tapAsync(pluginName, (compilation, callback: () => void) => { |
134 |
| - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access |
135 |
| - const outputPath = (compilation.outputOptions.path as string | undefined) ?? path.resolve(); |
136 |
| - const buildArtifacts = Object.keys(compilation.assets as Record<string, unknown>).map( |
137 |
| - (asset) => path.join(outputPath, asset) |
138 |
| - ); |
139 |
| - void upload(buildArtifacts).then(() => { |
140 |
| - callback(); |
141 |
| - }); |
142 |
| - }); |
143 |
| - |
144 |
| - if (forceExitOnBuildCompletion && compiler.options.mode === "production") { |
145 |
| - compiler.hooks.done.tap(pluginName, () => { |
146 |
| - setTimeout(() => { |
147 |
| - logger.debug("Exiting process after debug file upload"); |
148 |
| - process.exit(0); |
149 |
| - }); |
150 |
| - }); |
151 |
| - } |
152 |
| - }, |
153 |
| - }; |
154 |
| -} |
155 |
| - |
156 |
| -function webpackModuleMetadataInjectionPlugin(injectionCode: string): UnpluginOptions { |
157 |
| - return { |
158 |
| - name: "sentry-webpack-module-metadata-injection-plugin", |
159 |
| - webpack(compiler) { |
160 |
| - // eslint-disable-next-line @typescript-eslint/ban-ts-comment |
161 |
| - // @ts-ignore webpack version compatibility shenanigans |
162 |
| - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access |
163 |
| - const BannerPlugin = |
164 |
| - // eslint-disable-next-line @typescript-eslint/ban-ts-comment |
165 |
| - // @ts-ignore webpack version compatibility shenanigans |
166 |
| - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access |
167 |
| - compiler?.webpack?.BannerPlugin || |
168 |
| - webpack4or5?.BannerPlugin || |
169 |
| - webpack4or5?.default?.BannerPlugin; |
170 |
| - compiler.options.plugins = compiler.options.plugins || []; |
171 |
| - compiler.options.plugins.push( |
172 |
| - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call |
173 |
| - new BannerPlugin({ |
174 |
| - raw: true, |
175 |
| - include: /\.(js|ts|jsx|tsx|mjs|cjs)(\?[^?]*)?(#[^#]*)?$/, |
176 |
| - banner: injectionCode, |
177 |
| - }) |
178 |
| - ); |
179 |
| - }, |
180 |
| - }; |
181 |
| -} |
182 |
| - |
183 |
| -const sentryUnplugin = sentryUnpluginFactory({ |
184 |
| - releaseInjectionPlugin: webpackReleaseInjectionPlugin, |
185 |
| - componentNameAnnotatePlugin: webpackComponentNameAnnotatePlugin, |
186 |
| - moduleMetadataInjectionPlugin: webpackModuleMetadataInjectionPlugin, |
187 |
| - debugIdInjectionPlugin: webpackDebugIdInjectionPlugin, |
188 |
| - debugIdUploadPlugin: webpackDebugIdUploadPlugin, |
189 |
| - bundleSizeOptimizationsPlugin: webpackBundleSizeOptimizationsPlugin, |
| 11 | +const sentryUnplugin = sentryWebpackUnpluginFactory({ |
| 12 | + BannerPlugin, |
| 13 | + DefinePlugin, |
190 | 14 | });
|
191 | 15 |
|
192 |
| -type SentryWebpackPluginOptions = Options & { |
193 |
| - _experiments?: Options["_experiments"] & { |
194 |
| - /** |
195 |
| - * If enabled, the webpack plugin will exit the build process after the build completes. |
196 |
| - * Use this with caution, as it will terminate the process. |
197 |
| - * |
198 |
| - * More information: https://github.com/getsentry/sentry-javascript-bundler-plugins/issues/345 |
199 |
| - * |
200 |
| - * @default false |
201 |
| - */ |
202 |
| - forceExitOnBuildCompletion?: boolean; |
203 |
| - }; |
204 |
| -}; |
205 |
| - |
206 | 16 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
207 | 17 | export const sentryWebpackPlugin: (options?: SentryWebpackPluginOptions) => any =
|
208 | 18 | sentryUnplugin.webpack;
|
|
0 commit comments