Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

feat(vite, webpack): allow client-side sourcemaps in production #7313

Merged
merged 10 commits into from
Sep 7, 2022
23 changes: 13 additions & 10 deletions packages/nuxt/src/components/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { TreeShakeTemplatePlugin } from './tree-shake'

const isPureObjectOrString = (val: any) => (!Array.isArray(val) && typeof val === 'object') || typeof val === 'string'
const isDirectory = (p: string) => { try { return statSync(p).isDirectory() } catch (_e) { return false } }
function compareDirByPathLength ({ path: pathA }: { path: string}, { path: pathB }: { path: string}) {
function compareDirByPathLength ({ path: pathA }: { path: string }, { path: pathB }: { path: string }) {
return pathB.split(/[\\/]/).filter(Boolean).length - pathA.split(/[\\/]/).filter(Boolean).length
}

Expand Down Expand Up @@ -165,31 +165,34 @@ export default defineNuxtModule<ComponentsOptions>({
}
})

nuxt.hook('vite:extendConfig', (config, { isClient }) => {
nuxt.hook('vite:extendConfig', (config, { isClient, isServer }) => {
const mode = isClient ? 'client' : 'server'

config.plugins = config.plugins || []
config.plugins.push(loaderPlugin.vite({
sourcemap: nuxt.options.sourcemap,
sourcemap: nuxt.options.sourcemap[mode],
getComponents,
mode: isClient ? 'client' : 'server'
mode
}))
if (nuxt.options.experimental.treeshakeClientOnly) {
if (nuxt.options.experimental.treeshakeClientOnly && isServer) {
config.plugins.push(TreeShakeTemplatePlugin.vite({
sourcemap: nuxt.options.sourcemap,
sourcemap: nuxt.options.sourcemap[mode],
getComponents
}))
}
})
nuxt.hook('webpack:config', (configs) => {
configs.forEach((config) => {
const mode = config.name === 'client' ? 'client' : 'server'
config.plugins = config.plugins || []
config.plugins.push(loaderPlugin.webpack({
sourcemap: nuxt.options.sourcemap,
sourcemap: nuxt.options.sourcemap[mode],
getComponents,
mode: config.name === 'client' ? 'client' : 'server'
mode
}))
if (nuxt.options.experimental.treeshakeClientOnly) {
if (nuxt.options.experimental.treeshakeClientOnly && mode === 'server') {
config.plugins.push(TreeShakeTemplatePlugin.webpack({
sourcemap: nuxt.options.sourcemap,
sourcemap: nuxt.options.sourcemap[mode],
getComponents
}))
}
Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/src/core/nitro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export async function initNitro (nuxt: Nuxt) {
.concat(nuxt.options._generate ? ['/', ...nuxt.options.generate.routes] : [])
.concat(nuxt.options.ssr === false ? ['/', '/200.html', '/404.html'] : [])
},
sourcemap: nuxt.options.sourcemap,
sourceMap: nuxt.options.sourcemap.server,
externals: {
inline: [
...(nuxt.options.dev
Expand Down
12 changes: 6 additions & 6 deletions packages/nuxt/src/core/nuxt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,18 @@ async function initNuxt (nuxt: Nuxt) {
addWebpackPlugin(ImportProtectionPlugin.webpack(config))

// Add unctx transform
addVitePlugin(UnctxTransformPlugin(nuxt).vite({ sourcemap: nuxt.options.sourcemap }))
addWebpackPlugin(UnctxTransformPlugin(nuxt).webpack({ sourcemap: nuxt.options.sourcemap }))
addVitePlugin(UnctxTransformPlugin(nuxt).vite({ sourcemap: nuxt.options.sourcemap.server || nuxt.options.sourcemap.client }))
addWebpackPlugin(UnctxTransformPlugin(nuxt).webpack({ sourcemap: nuxt.options.sourcemap.server || nuxt.options.sourcemap.client }))

if (!nuxt.options.dev) {
const removeFromServer = ['onBeforeMount', 'onMounted', 'onBeforeUpdate', 'onRenderTracked', 'onRenderTriggered', 'onActivated', 'onDeactivated', 'onBeforeUnmount']
const removeFromClient = ['onServerPrefetch', 'onRenderTracked', 'onRenderTriggered']

// Add tree-shaking optimisations for SSR - build time only
addVitePlugin(TreeShakePlugin.vite({ sourcemap: nuxt.options.sourcemap, treeShake: removeFromServer }), { client: false })
addVitePlugin(TreeShakePlugin.vite({ sourcemap: nuxt.options.sourcemap, treeShake: removeFromClient }), { server: false })
addWebpackPlugin(TreeShakePlugin.webpack({ sourcemap: nuxt.options.sourcemap, treeShake: removeFromServer }), { client: false })
addWebpackPlugin(TreeShakePlugin.webpack({ sourcemap: nuxt.options.sourcemap, treeShake: removeFromClient }), { server: false })
addVitePlugin(TreeShakePlugin.vite({ sourcemap: nuxt.options.sourcemap.server, treeShake: removeFromServer }), { client: false })
addVitePlugin(TreeShakePlugin.vite({ sourcemap: nuxt.options.sourcemap.client, treeShake: removeFromClient }), { server: false })
addWebpackPlugin(TreeShakePlugin.webpack({ sourcemap: nuxt.options.sourcemap.server, treeShake: removeFromServer }), { client: false })
addWebpackPlugin(TreeShakePlugin.webpack({ sourcemap: nuxt.options.sourcemap.client, treeShake: removeFromClient }), { server: false })
}

// TODO: [Experimental] Avoid emitting assets when flag is enabled
Expand Down
4 changes: 2 additions & 2 deletions packages/nuxt/src/imports/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ export default defineNuxtModule<Partial<ImportsOptions>>({
})
} else {
// Transform to inject imports in production mode
addVitePlugin(TransformPlugin.vite({ ctx, options, sourcemap: nuxt.options.sourcemap }))
addWebpackPlugin(TransformPlugin.webpack({ ctx, options, sourcemap: nuxt.options.sourcemap }))
addVitePlugin(TransformPlugin.vite({ ctx, options, sourcemap: nuxt.options.sourcemap.server || nuxt.options.sourcemap.client }))
addWebpackPlugin(TransformPlugin.webpack({ ctx, options, sourcemap: nuxt.options.sourcemap.server || nuxt.options.sourcemap.client }))
}

const regenerateImports = async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/src/pages/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export default defineNuxtModule({
// Extract macros from pages
const macroOptions: TransformMacroPluginOptions = {
dev: nuxt.options.dev,
sourcemap: nuxt.options.sourcemap,
sourcemap: nuxt.options.sourcemap.server || nuxt.options.sourcemap.client,
macros: {
definePageMeta: 'meta'
}
Expand Down
13 changes: 12 additions & 1 deletion packages/schema/src/config/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,20 @@ export default defineUntypedSchema({
/**
* Whether to generate sourcemaps.
*
* @type {boolean | { server?: boolean, client?: boolean }}
* @version 3
*/
sourcemap: true,
sourcemap: {
$resolve: (val, get) => {
if (typeof val === 'boolean') {
return { server: val, client: val }
}
return defu(val, {
server: true,
client: get('dev')
})
},
},
/**
* Shared build configuration.
* @version 2
Expand Down
7 changes: 4 additions & 3 deletions packages/schema/src/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export type NuxtConfigLayer = ConfigLayer<NuxtConfig & {

/** Normalized Nuxt options available as `nuxt.options.*` */
export interface NuxtOptions extends ConfigSchema {
sourcemap: Required<Exclude<ConfigSchema['sourcemap'], boolean>>
_layers: NuxtConfigLayer[]
}

Expand Down Expand Up @@ -58,11 +59,11 @@ export interface ViteConfig extends ViteUserConfig {

type RuntimeConfigNamespace = Record<string, any>

export interface PublicRuntimeConfig extends RuntimeConfigNamespace { }
export interface PublicRuntimeConfig extends RuntimeConfigNamespace {}

// TODO: remove before release of 3.0.0
/** @deprecated use RuntimeConfig interface */
export interface PrivateRuntimeConfig extends RuntimeConfigNamespace { }
export interface PrivateRuntimeConfig extends RuntimeConfigNamespace {}

export interface RuntimeConfig extends PrivateRuntimeConfig, RuntimeConfigNamespace {
public: PublicRuntimeConfig
Expand All @@ -85,4 +86,4 @@ export interface NuxtAppConfig {
keepalive: boolean | KeepAliveProps
}

export interface AppConfig { }
export interface AppConfig {}
1 change: 1 addition & 0 deletions packages/vite/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export async function buildClient (ctx: ViteBuildContext) {
dedupe: ['vue']
},
build: {
sourcemap: ctx.nuxt.options.sourcemap.client,
manifest: true,
outDir: resolve(ctx.nuxt.options.buildDir, 'dist/client'),
rollupOptions: {
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export async function buildServer (ctx: ViteBuildContext) {
]
},
build: {
sourcemap: ctx.nuxt.options.sourcemap.server,
outDir: resolve(ctx.nuxt.options.buildDir, 'dist/server'),
ssr: ctx.nuxt.options.ssr ?? true,
rollupOptions: {
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export async function bundle (nuxt: Nuxt) {
}
},
plugins: [
composableKeysPlugin.vite({ sourcemap: nuxt.options.sourcemap, rootDir: nuxt.options.rootDir }),
composableKeysPlugin.vite({ sourcemap: nuxt.options.sourcemap.server || nuxt.options.sourcemap.client, rootDir: nuxt.options.rootDir }),
replace({
...Object.fromEntries([';', '(', '{', '}', ' ', '\t', '\n'].map(d => [`${d}global.`, `${d}globalThis.`])),
preventAssignment: true
Expand Down
7 changes: 6 additions & 1 deletion packages/webpack/src/configs/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@ export function client (ctx: WebpackConfigContext) {
}

function clientDevtool (ctx: WebpackConfigContext) {
if (!ctx.isDev) {
if (!ctx.nuxt.options.sourcemap.client) {
ctx.config.devtool = false
return
}

if (!ctx.isDev) {
ctx.config.devtool = 'source-map'
return
}

const scriptPolicy = getCspScriptPolicy(ctx)
const noUnsafeEval = scriptPolicy && !scriptPolicy.includes('\'unsafe-eval\'')
ctx.config.devtool = noUnsafeEval
Expand Down
3 changes: 2 additions & 1 deletion packages/webpack/src/configs/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ function serverPreset (ctx: WebpackConfigContext) {
const { config } = ctx

config.output!.filename = 'server.mjs'
config.devtool = 'cheap-module-source-map'

config.devtool = ctx.nuxt.options.sourcemap.server ? ctx.isDev ? 'cheap-module-source-map' : 'source-map' : false

config.optimization = {
splitChunks: false,
Expand Down
4 changes: 2 additions & 2 deletions packages/webpack/src/webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ export async function bundle (nuxt: Nuxt) {
// Configure compilers
const compilers = webpackConfigs.map((config) => {
config.plugins!.push(DynamicBasePlugin.webpack({
sourcemap: nuxt.options.sourcemap
sourcemap: nuxt.options.sourcemap[config.name as 'client' | 'server']
}))
config.plugins!.push(composableKeysPlugin.webpack({
sourcemap: nuxt.options.sourcemap,
sourcemap: nuxt.options.sourcemap[config.name as 'client' | 'server'],
rootDir: nuxt.options.rootDir
}))

Expand Down