feat: mode for plugins (#4592)

This commit is contained in:
Xin Du (Clark) 2018-12-20 09:28:10 +00:00 committed by Pooya Parsa
parent 40928967ac
commit e71c4559ff
9 changed files with 48 additions and 12 deletions

View File

@ -110,9 +110,19 @@ export default class Builder {
/[^a-zA-Z?\d\s:]/g, /[^a-zA-Z?\d\s:]/g,
'' ''
) )
if (p.ssr === false) {
p.mode = 'client'
} else if (p.mode === undefined) {
p.mode = 'all'
} else if (!['client', 'server'].includes(p.mode)) {
consola.warn(`Invalid plugin mode (server/client/all): '${p.mode}'. Falling back to 'all'`)
p.mode = 'all'
}
return { return {
src: this.nuxt.resolver.resolveAlias(p.src), src: this.nuxt.resolver.resolveAlias(p.src),
ssr: p.ssr !== false, mode: p.mode,
name: 'nuxt_plugin_' + pluginBaseName + '_' + hash(p.src) name: 'nuxt_plugin_' + pluginBaseName + '_' + hash(p.src)
} }
}), }),
@ -135,6 +145,15 @@ export default class Builder {
}) })
} }
const modes = ['client', 'server']
const modernPattern = new RegExp(`\\.(${modes.join('|')})\\.\\w+$`)
pluginFiles[0].replace(modernPattern, (_, mode) => {
// mode in nuxt.config has higher priority
if (p.mode === 'all' && modes.includes(mode)) {
p.mode = mode
}
})
p.src = this.relativeToBuild(p.src) p.src = this.relativeToBuild(p.src)
})) }))
} }

View File

@ -63,7 +63,9 @@ export default class ModuleContainer {
// Add to nuxt plugins // Add to nuxt plugins
this.options.plugins.unshift({ this.options.plugins.unshift({
src: path.join(this.options.buildDir, dst), src: path.join(this.options.buildDir, dst),
ssr: template.ssr // TODO: remove deprecated option in Nuxt 3
ssr: template.ssr,
mode: template.mode
}) })
} }

View File

@ -12,7 +12,7 @@ import { setContext, getLocation, getRouteData, normalizeError } from './utils'
/* Plugins */ /* Plugins */
<%= isTest ? '/* eslint-disable camelcase */' : '' %> <%= isTest ? '/* eslint-disable camelcase */' : '' %>
<% plugins.forEach((plugin) => { %>import <%= plugin.name %> from '<%= plugin.name %>' // Source: <%= relativeToBuild(plugin.src) %><%= (plugin.ssr===false) ? ' (ssr: false)' : '' %> <% plugins.forEach((plugin) => { %>import <%= plugin.name %> from '<%= plugin.name %>' // Source: <%= relativeToBuild(plugin.src) %> (mode: '<%= plugin.mode %>')
<% }) %> <% }) %>
<%= isTest ? '/* eslint-enable camelcase */' : '' %> <%= isTest ? '/* eslint-enable camelcase */' : '' %>
@ -168,11 +168,18 @@ async function createApp(ssrContext) {
// Plugin execution // Plugin execution
<%= isTest ? '/* eslint-disable camelcase */' : '' %> <%= isTest ? '/* eslint-disable camelcase */' : '' %>
<% plugins.filter(p => p.ssr).forEach((plugin) => { %> <% plugins.filter(p => p.mode === 'all').forEach((plugin) => { %>
if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(app.context, inject)<% }) %> if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(app.context, inject)<% }) %>
<% if (plugins.filter(p => !p.ssr).length) { %>
<% if (plugins.filter(p => p.mode === 'client').length) { %>
if (process.client) { if (process.client) {
<% plugins.filter((p) => !p.ssr).forEach((plugin) => { %> <% plugins.filter(p => p.mode === 'client').forEach((plugin) => { %>
if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(app.context, inject)<% }) %>
}<% } %>
<% if (plugins.filter(p => p.mode === 'server').length) { %>
if (process.server) {
<% plugins.filter(p => p.mode === 'server').forEach((plugin) => { %>
if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(app.context, inject)<% }) %> if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(app.context, inject)<% }) %>
}<% } %> }<% } %>
<%= isTest ? '/* eslint-enable camelcase */' : '' %> <%= isTest ? '/* eslint-enable camelcase */' : '' %>

View File

@ -63,18 +63,17 @@ export class WebpackBundler {
for (const p of this.context.plugins) { for (const p of this.context.plugins) {
// Client config // Client config
if (!clientConfig.resolve.alias[p.name]) { if (!clientConfig.resolve.alias[p.name]) {
clientConfig.resolve.alias[p.name] = p.src clientConfig.resolve.alias[p.name] = p.mode === 'server' ? './empty.js' : p.src
} }
// Server config // Server config
if (serverConfig && !serverConfig.resolve.alias[p.name]) { if (serverConfig && !serverConfig.resolve.alias[p.name]) {
// Alias to noop for ssr:false plugins serverConfig.resolve.alias[p.name] = p.mode === 'client' ? './empty.js' : p.src
serverConfig.resolve.alias[p.name] = p.ssr ? p.src : './empty.js'
} }
// Modern config // Modern config
if (modernConfig && !modernConfig.resolve.alias[p.name]) { if (modernConfig && !modernConfig.resolve.alias[p.name]) {
modernConfig.resolve.alias[p.name] = p.src modernConfig.resolve.alias[p.name] = p.mode === 'client' ? './empty.js' : p.src
} }
} }

View File

@ -37,7 +37,9 @@ export default {
extensions: 'ts', extensions: 'ts',
plugins: [ plugins: [
'~/plugins/test', '~/plugins/test',
'~/plugins/test.plugin', { src: '~/plugins/test.plugin', mode: 'abc' },
'~/plugins/test.client',
'~/plugins/test.server',
{ src: '~/plugins/only-client.js', ssr: false } { src: '~/plugins/only-client.js', ssr: false }
], ],
loading: '~/components/loading', loading: '~/components/loading',

View File

@ -0,0 +1 @@
window.__test_plugin_client = 'test_plugin_client'

View File

@ -0,0 +1 @@
global.__test_plugin_server = 'test_plugin_server'

View File

@ -14,12 +14,15 @@ const hooks = [
describe('with-config', () => { describe('with-config', () => {
buildFixture('with-config', () => { buildFixture('with-config', () => {
expect(consola.warn).toHaveBeenCalledTimes(4) expect(consola.warn).toHaveBeenCalledTimes(5)
expect(consola.fatal).toHaveBeenCalledTimes(0) expect(consola.fatal).toHaveBeenCalledTimes(0)
expect(consola.warn.mock.calls).toMatchObject([ expect(consola.warn.mock.calls).toMatchObject([
[ [
'Unknown mode: unknown. Falling back to universal' 'Unknown mode: unknown. Falling back to universal'
], ],
[
`Invalid plugin mode (server/client/all): 'abc'. Falling back to 'all'`
],
[{ [{
message: 'Found 2 plugins that match the configuration, suggest to specify extension:', message: 'Found 2 plugins that match the configuration, suggest to specify extension:',
additional: expect.stringContaining('plugins/test.json') additional: expect.stringContaining('plugins/test.json')

View File

@ -91,6 +91,8 @@ describe('with-config', () => {
expect(window.__test_plugin).toBe(true) expect(window.__test_plugin).toBe(true)
expect(window.__test_plugin_ext).toBe(true) expect(window.__test_plugin_ext).toBe(true)
expect(window.__test_plugin_client).toBe('test_plugin_client')
expect(window.__test_plugin_server).toBeUndefined()
}) })
test('/test/about (custom layout)', async () => { test('/test/about (custom layout)', async () => {