2021-07-27 17:07:28 +02:00
/ *
Copyright ( c ) 2017 The swc Project Developers
Permission is hereby granted , free of charge , to any
person obtaining a copy of this software and associated
documentation files ( the "Software" ) , to deal in the
Software without restriction , including without
limitation the rights to use , copy , modify , merge ,
publish , distribute , sublicense , and / or sell copies of
the Software , and to permit persons to whom the Software
is furnished to do so , subject to the following
conditions :
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software .
THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF
ANY KIND , EXPRESS OR IMPLIED , INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY , FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM , DAMAGES OR OTHER LIABILITY , WHETHER IN AN ACTION
OF CONTRACT , TORT OR OTHERWISE , ARISING FROM , OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE .
* /
2021-08-06 16:07:36 +02:00
import { transform } from '../../swc'
2021-09-16 16:11:30 +02:00
const nextDistPath =
/(next[\\/]dist[\\/]shared[\\/]lib)|(next[\\/]dist[\\/]client)|(next[\\/]dist[\\/]pages)/
2021-09-14 18:13:11 +02:00
function getSWCOptions ( {
2021-10-30 14:51:42 +02:00
filename ,
2021-09-14 18:13:11 +02:00
isServer ,
development ,
isPageFile ,
pagesDir ,
2021-09-16 16:11:30 +02:00
isNextDist ,
2021-10-24 15:25:02 +02:00
hasReactRefresh ,
2021-09-14 18:13:11 +02:00
} ) {
2021-10-30 14:51:42 +02:00
const isTSFile = filename . endsWith ( '.ts' )
const isTypeScript = isTSFile || filename . endsWith ( '.tsx' )
2021-08-06 16:07:36 +02:00
const jsc = {
parser : {
syntax : isTypeScript ? 'typescript' : 'ecmascript' ,
dynamicImport : true ,
2021-10-30 14:51:42 +02:00
// Exclude regular TypeScript files from React transformation to prevent e.g. generic parameters and angle-bracket type assertion from being interpreted as JSX tags.
[ isTypeScript ? 'tsx' : 'jsx' ] : isTSFile ? false : true ,
2021-08-06 16:07:36 +02:00
} ,
transform : {
react : {
runtime : 'automatic' ,
pragma : 'React.createElement' ,
pragmaFrag : 'React.Fragment' ,
throwIfNamespace : true ,
development : development ,
useBuiltins : true ,
2021-10-24 15:25:02 +02:00
refresh : hasReactRefresh ,
2021-08-06 16:07:36 +02:00
} ,
2021-10-23 10:21:44 +02:00
optimizer : {
simplify : false ,
globals : {
typeofs : {
window : isServer ? 'undefined' : 'object' ,
} ,
} ,
} ,
2021-11-02 12:11:53 +01:00
regenerator : {
importPath : require . resolve ( 'regenerator-runtime' ) ,
} ,
2021-08-06 16:07:36 +02:00
} ,
}
2021-07-27 17:07:28 +02:00
2021-08-06 16:07:36 +02:00
if ( isServer ) {
return {
jsc ,
2021-09-13 12:20:38 +02:00
// Disables getStaticProps/getServerSideProps tree shaking on the server compilation for pages
disableNextSsg : true ,
2021-10-23 01:08:09 +02:00
disablePageConfig : true ,
isDevelopment : development ,
2021-09-14 18:13:11 +02:00
pagesDir ,
2021-10-23 10:21:44 +02:00
isPageFile ,
2021-08-06 16:07:36 +02:00
env : {
targets : {
// Targets the current version of Node.js
node : process . versions . node ,
} ,
} ,
2021-07-27 17:07:28 +02:00
}
2021-08-06 16:07:36 +02:00
} else {
// Matches default @babel/preset-env behavior
jsc . target = 'es5'
2021-09-14 18:13:11 +02:00
return {
2021-09-16 16:11:30 +02:00
// Ensure Next.js internals are output as commonjs modules
2021-10-31 00:37:35 +02:00
... ( isNextDist
2021-09-16 16:11:30 +02:00
? {
module : {
type : 'commonjs' ,
} ,
}
: { } ) ,
2021-09-14 18:13:11 +02:00
disableNextSsg : ! isPageFile ,
2021-10-23 01:08:09 +02:00
isDevelopment : development ,
2021-09-14 18:13:11 +02:00
pagesDir ,
2021-10-23 10:21:44 +02:00
isPageFile ,
2021-09-14 18:13:11 +02:00
jsc ,
}
2021-08-06 16:07:36 +02:00
}
}
2021-07-27 17:07:28 +02:00
2021-08-06 16:07:36 +02:00
async function loaderTransform ( parentTrace , source , inputSourceMap ) {
// Make the loader async
const filename = this . resourcePath
2021-07-27 17:07:28 +02:00
2021-11-02 16:13:15 +01:00
let loaderOptions = this . getOptions ( ) || { }
2021-07-27 17:07:28 +02:00
2021-10-24 15:25:02 +02:00
const { isServer , pagesDir , hasReactRefresh } = loaderOptions
2021-09-13 12:20:38 +02:00
const isPageFile = filename . startsWith ( pagesDir )
2021-09-16 16:11:30 +02:00
const isNextDist = nextDistPath . test ( filename )
2021-08-06 16:07:36 +02:00
const swcOptions = getSWCOptions ( {
2021-09-14 18:13:11 +02:00
pagesDir ,
2021-10-30 14:51:42 +02:00
filename ,
2021-09-13 12:20:38 +02:00
isServer : isServer ,
isPageFile ,
2021-08-06 16:07:36 +02:00
development : this . mode === 'development' ,
2021-09-16 16:11:30 +02:00
isNextDist ,
2021-10-24 15:25:02 +02:00
hasReactRefresh ,
2021-08-06 16:07:36 +02:00
} )
const programmaticOptions = {
... swcOptions ,
filename ,
inputSourceMap : inputSourceMap ? JSON . stringify ( inputSourceMap ) : undefined ,
// Set the default sourcemap behavior based on Webpack's mapping flag,
sourceMaps : this . sourceMap ,
2021-10-09 16:39:53 +02:00
inlineSourcesContent : this . sourceMap ,
2021-08-06 16:07:36 +02:00
// Ensure that Webpack will get a full absolute path in the sourcemap
// so that it can properly map the module back to its internal cached
// modules.
sourceFileName : filename ,
}
if ( ! programmaticOptions . inputSourceMap ) {
delete programmaticOptions . inputSourceMap
}
// auto detect development mode
if (
this . mode &&
programmaticOptions . jsc &&
programmaticOptions . jsc . transform &&
programmaticOptions . jsc . transform . react &&
! Object . prototype . hasOwnProperty . call (
programmaticOptions . jsc . transform . react ,
'development'
)
) {
programmaticOptions . jsc . transform . react . development =
this . mode === 'development'
2021-07-27 17:07:28 +02:00
}
2021-08-06 16:07:36 +02:00
const swcSpan = parentTrace . traceChild ( 'next-swc-transform' )
return swcSpan . traceAsyncFn ( ( ) =>
transform ( source , programmaticOptions ) . then ( ( output ) => {
return [ output . code , output . map ? JSON . parse ( output . map ) : undefined ]
} )
)
2021-07-27 17:07:28 +02:00
}
2021-08-06 16:07:36 +02:00
export default function swcLoader ( inputSource , inputSourceMap ) {
2021-08-25 10:47:16 +02:00
const loaderSpan = this . currentTraceSpan . traceChild ( 'next-swc-loader' )
2021-08-06 16:07:36 +02:00
const callback = this . async ( )
loaderSpan
. traceAsyncFn ( ( ) =>
loaderTransform . call ( this , loaderSpan , inputSource , inputSourceMap )
)
. then (
2021-09-16 16:11:30 +02:00
( [ transformedSource , outputSourceMap ] ) => {
callback ( null , transformedSource , outputSourceMap || inputSourceMap )
} ,
2021-08-06 16:07:36 +02:00
( err ) => {
2021-09-16 16:11:30 +02:00
callback ( err )
2021-08-06 16:07:36 +02:00
}
)
}