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,
''
)
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 {
src: this.nuxt.resolver.resolveAlias(p.src),
ssr: p.ssr !== false,
mode: p.mode,
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)
}))
}

View File

@ -63,7 +63,9 @@ export default class ModuleContainer {
// Add to nuxt plugins
this.options.plugins.unshift({
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 */
<%= 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 */' : '' %>
@ -168,11 +168,18 @@ async function createApp(ssrContext) {
// Plugin execution
<%= 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 (plugins.filter(p => !p.ssr).length) { %>
<% if (plugins.filter(p => p.mode === 'client').length) { %>
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)<% }) %>
}<% } %>
<%= isTest ? '/* eslint-enable camelcase */' : '' %>

View File

@ -63,18 +63,17 @@ export class WebpackBundler {
for (const p of this.context.plugins) {
// Client config
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
if (serverConfig && !serverConfig.resolve.alias[p.name]) {
// Alias to noop for ssr:false plugins
serverConfig.resolve.alias[p.name] = p.ssr ? p.src : './empty.js'
serverConfig.resolve.alias[p.name] = p.mode === 'client' ? './empty.js' : p.src
}
// Modern config
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',
plugins: [
'~/plugins/test',
'~/plugins/test.plugin',
{ src: '~/plugins/test.plugin', mode: 'abc' },
'~/plugins/test.client',
'~/plugins/test.server',
{ src: '~/plugins/only-client.js', ssr: false }
],
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', () => {
buildFixture('with-config', () => {
expect(consola.warn).toHaveBeenCalledTimes(4)
expect(consola.warn).toHaveBeenCalledTimes(5)
expect(consola.fatal).toHaveBeenCalledTimes(0)
expect(consola.warn.mock.calls).toMatchObject([
[
'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:',
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_ext).toBe(true)
expect(window.__test_plugin_client).toBe('test_plugin_client')
expect(window.__test_plugin_server).toBeUndefined()
})
test('/test/about (custom layout)', async () => {