mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-29 09:02:03 +00:00
feat: support auto import of plugins (#169)
This commit is contained in:
parent
498a234039
commit
bece3b85ab
@ -1,9 +1,12 @@
|
|||||||
import '@nuxt/nitro/dist/runtime/app/nitro.client'
|
import '@nuxt/nitro/dist/runtime/app/nitro.client'
|
||||||
import logs from 'nuxt/app/plugins/logs.client.dev'
|
import logs from 'nuxt/app/plugins/logs.client.dev'
|
||||||
import progress from 'nuxt/app/plugins/progress.client'
|
import progress from 'nuxt/app/plugins/progress.client'
|
||||||
|
<% const plugins = app.plugins.filter(p => p.mode === 'client').map(p => p.src) %>
|
||||||
|
<%= nxt.importSources(plugins) %>
|
||||||
|
|
||||||
const plugins = [
|
const plugins = [
|
||||||
progress
|
progress,
|
||||||
|
<%= plugins.map(nxt.importName).join(',\n\t') %>
|
||||||
]
|
]
|
||||||
|
|
||||||
if (process.dev) {
|
if (process.dev) {
|
||||||
|
@ -3,9 +3,13 @@ import router from 'nuxt/app/plugins/router'
|
|||||||
import vuex from 'nuxt/app/plugins/vuex'
|
import vuex from 'nuxt/app/plugins/vuex'
|
||||||
import legacy from 'nuxt/app/plugins/legacy'
|
import legacy from 'nuxt/app/plugins/legacy'
|
||||||
|
|
||||||
|
<% const plugins = app.plugins.filter(p => p.mode === 'all').map(p => p.src) %>
|
||||||
|
<%= nxt.importSources(plugins) %>
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
head,
|
head,
|
||||||
router,
|
router,
|
||||||
vuex,
|
vuex,
|
||||||
legacy
|
legacy,
|
||||||
|
<%= plugins.map(nxt.importName).join(',\n\t') %>
|
||||||
]
|
]
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import preload from 'nuxt/app/plugins/preload.server'
|
import preload from 'nuxt/app/plugins/preload.server'
|
||||||
|
<% const plugins = app.plugins.filter(p => p.mode === 'server').map(p => p.src) %>
|
||||||
|
<%= nxt.importSources(plugins) %>
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
preload
|
preload
|
||||||
|
<%= plugins.map(nxt.importName).join(',\n\t') %>
|
||||||
]
|
]
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
// TODO: Use webpack-virtual-modules
|
// TODO: Use webpack-virtual-modules
|
||||||
export default <%= app.templates.routes || '[]' %>
|
export default <%= nxt.serialize(app.routes.map(nxt.serializeRoute)) %>
|
||||||
|
@ -81,6 +81,7 @@ export function createNuxt (options: CreateOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function applyPlugin (nuxt: Nuxt, plugin: Plugin) {
|
export function applyPlugin (nuxt: Nuxt, plugin: Plugin) {
|
||||||
|
if (typeof plugin !== 'function') { return }
|
||||||
return callWithNuxt(nuxt, () => plugin(nuxt))
|
return callWithNuxt(nuxt, () => plugin(nuxt))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ export default <Plugin> function router (nuxt) {
|
|||||||
routes
|
routes
|
||||||
})
|
})
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
nuxt.provide('router', router)
|
||||||
|
|
||||||
const previousRoute = shallowRef(router.currentRoute.value)
|
const previousRoute = shallowRef(router.currentRoute.value)
|
||||||
router.afterEach((_to, from) => {
|
router.afterEach((_to, from) => {
|
||||||
@ -35,7 +36,7 @@ export default <Plugin> function router (nuxt) {
|
|||||||
get: () => previousRoute.value
|
get: () => previousRoute.value
|
||||||
})
|
})
|
||||||
|
|
||||||
nuxt.hooks.hook('app:created', async () => {
|
nuxt.hook('app:created', async () => {
|
||||||
if (process.server) {
|
if (process.server) {
|
||||||
router.push(nuxt.ssrContext.url)
|
router.push(nuxt.ssrContext.url)
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,13 @@ import { resolve } from 'path'
|
|||||||
import defu from 'defu'
|
import defu from 'defu'
|
||||||
import { Builder } from './builder'
|
import { Builder } from './builder'
|
||||||
import { NuxtRoute, resolvePagesRoutes } from './pages'
|
import { NuxtRoute, resolvePagesRoutes } from './pages'
|
||||||
|
import { NuxtPlugin, resolvePlugins } from './plugins'
|
||||||
export interface NuxtApp {
|
export interface NuxtApp {
|
||||||
main: string
|
main: string
|
||||||
routes: NuxtRoute[]
|
routes: NuxtRoute[]
|
||||||
dir: string
|
dir: string
|
||||||
extensions: string[]
|
extensions: string[]
|
||||||
|
plugins: NuxtPlugin[]
|
||||||
templates: Record<string, string>
|
templates: Record<string, string>
|
||||||
pages?: {
|
pages?: {
|
||||||
dir: string
|
dir: string
|
||||||
@ -26,6 +27,7 @@ export async function createApp (
|
|||||||
dir: nuxt.options.srcDir,
|
dir: nuxt.options.srcDir,
|
||||||
extensions: nuxt.options.extensions,
|
extensions: nuxt.options.extensions,
|
||||||
routes: [],
|
routes: [],
|
||||||
|
plugins: [],
|
||||||
templates: {},
|
templates: {},
|
||||||
pages: {
|
pages: {
|
||||||
dir: 'pages'
|
dir: 'pages'
|
||||||
@ -54,8 +56,6 @@ export async function createApp (
|
|||||||
children: []
|
children: []
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// TODO: Hook to extend routes
|
|
||||||
app.templates.routes = serializeRoutes(app.routes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback app.main
|
// Fallback app.main
|
||||||
@ -65,24 +65,8 @@ export async function createApp (
|
|||||||
app.main = resolve(nuxt.options.appDir, 'app.tutorial.vue')
|
app.main = resolve(nuxt.options.appDir, 'app.tutorial.vue')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve plugins/
|
||||||
|
app.plugins = await resolvePlugins(builder, app)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
function serializeRoutes (routes: NuxtRoute[]) {
|
|
||||||
return JSON.stringify(
|
|
||||||
routes.map(formatRoute),
|
|
||||||
null,
|
|
||||||
2
|
|
||||||
).replace(/"{(.+)}"/g, '$1')
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatRoute (route: NuxtRoute) {
|
|
||||||
return {
|
|
||||||
name: route.name,
|
|
||||||
path: route.path,
|
|
||||||
children: route.children.map(formatRoute),
|
|
||||||
// TODO: avoid exposing to prod, using process.env.NODE_ENV ?
|
|
||||||
__file: route.file,
|
|
||||||
component: `{() => import('${route.file}' /* webpackChunkName: '${route.name}' */)}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -65,6 +65,7 @@ function watch (builder: Builder) {
|
|||||||
nuxtAppWatcher.watchAll(debounce(() => compileTemplates(builder.templates, nuxt.options.buildDir), 100))
|
nuxtAppWatcher.watchAll(debounce(() => compileTemplates(builder.templates, nuxt.options.buildDir), 100))
|
||||||
|
|
||||||
// Watch user app
|
// Watch user app
|
||||||
|
// TODO: handle multiples app dirs
|
||||||
const appPattern = `${builder.app.dir}/**/*.{${nuxt.options.extensions.join(',')}}`
|
const appPattern = `${builder.app.dir}/**/*.{${nuxt.options.extensions.join(',')}}`
|
||||||
const appWatcher = createWatcher(appPattern, { ...options, cwd: builder.app.dir }, ignore)
|
const appWatcher = createWatcher(appPattern, { ...options, cwd: builder.app.dir }, ignore)
|
||||||
// appWatcher.debug('srcDir')
|
// appWatcher.debug('srcDir')
|
||||||
@ -73,6 +74,8 @@ function watch (builder: Builder) {
|
|||||||
appWatcher.watch(/^(A|a)pp\.[a-z]{2,3}/, refreshTemplates, ['add', 'unlink'])
|
appWatcher.watch(/^(A|a)pp\.[a-z]{2,3}/, refreshTemplates, ['add', 'unlink'])
|
||||||
// Watch for page changes
|
// Watch for page changes
|
||||||
appWatcher.watch(new RegExp(`^${nuxt.options.dir.pages}/`), refreshTemplates, ['add', 'unlink'])
|
appWatcher.watch(new RegExp(`^${nuxt.options.dir.pages}/`), refreshTemplates, ['add', 'unlink'])
|
||||||
|
// Watch for plugins changes
|
||||||
|
appWatcher.watch(/^plugins/, refreshTemplates, ['add', 'unlink'])
|
||||||
|
|
||||||
// Shared Watcher
|
// Shared Watcher
|
||||||
const watchHookDebounced = debounce((event, file) => builder.nuxt.callHook('builder:watch', event, file), 100)
|
const watchHookDebounced = debounce((event, file) => builder.nuxt.callHook('builder:watch', event, file), 100)
|
||||||
@ -84,9 +87,11 @@ export async function generate (builder: Builder) {
|
|||||||
const { nuxt } = builder
|
const { nuxt } = builder
|
||||||
|
|
||||||
builder.app = await createApp(builder)
|
builder.app = await createApp(builder)
|
||||||
|
// Todo: Call app:created hook
|
||||||
|
|
||||||
const templatesDir = join(builder.nuxt.options.appDir, '_templates')
|
const templatesDir = join(builder.nuxt.options.appDir, '_templates')
|
||||||
const appTemplates = await scanTemplates(templatesDir, templateData(builder))
|
const appTemplates = await scanTemplates(templatesDir, templateData(builder))
|
||||||
|
// Todo: Call app:templates hook
|
||||||
|
|
||||||
builder.templates = [...appTemplates]
|
builder.templates = [...appTemplates]
|
||||||
|
|
||||||
|
32
packages/nuxt3/src/builder/nxt.ts
Normal file
32
packages/nuxt3/src/builder/nxt.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { basename, extname } from 'path'
|
||||||
|
import hash from 'hash-sum'
|
||||||
|
import { camelCase } from 'scule'
|
||||||
|
import { NuxtRoute } from './pages'
|
||||||
|
// NXT is a set of utils for serializing JavaScript data to JS code
|
||||||
|
|
||||||
|
export const serialize = data => JSON.stringify(data, null, 2).replace(/"{(.+)}"/g, '$1')
|
||||||
|
|
||||||
|
export const importName = (src: string) => `${camelCase(basename(src, extname(src))).replace(/[^a-zA-Z?\d\s:]/g, '')}_${hash(src)}`
|
||||||
|
|
||||||
|
export const importSources = (sources: string | string[], { lazy = false } = {}) => {
|
||||||
|
if (!Array.isArray(sources)) {
|
||||||
|
sources = [sources]
|
||||||
|
}
|
||||||
|
return sources.map((src) => {
|
||||||
|
if (lazy) {
|
||||||
|
return `const ${importName(src)} = () => import('${src}' /* webpackChunkName: '${src}' */)`
|
||||||
|
}
|
||||||
|
return `import ${importName(src)} from '${src}'`
|
||||||
|
}).join('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
export const serializeRoute = (route: NuxtRoute) => {
|
||||||
|
return {
|
||||||
|
name: route.name,
|
||||||
|
path: route.path,
|
||||||
|
children: route.children.map(serializeRoute),
|
||||||
|
// TODO: avoid exposing to prod, using process.env.NODE_ENV ?
|
||||||
|
__file: route.file,
|
||||||
|
component: `{() => import('${route.file}' /* webpackChunkName: '${route.name}' */)}`
|
||||||
|
}
|
||||||
|
}
|
26
packages/nuxt3/src/builder/plugins.ts
Normal file
26
packages/nuxt3/src/builder/plugins.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
import { NuxtApp } from './app'
|
||||||
|
import { Builder } from './builder'
|
||||||
|
import { resolveFiles } from './utils'
|
||||||
|
|
||||||
|
export interface NuxtPlugin {
|
||||||
|
src: string
|
||||||
|
mode: 'server' | 'client' | 'all'
|
||||||
|
}
|
||||||
|
|
||||||
|
const MODES_REGEX = /\.(server|client)(\.\w+)*$/
|
||||||
|
const getPluginMode = (src) => {
|
||||||
|
const [, mode = 'all'] = src.match(MODES_REGEX) || []
|
||||||
|
|
||||||
|
return mode
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolvePlugins (builder: Builder, app: NuxtApp) {
|
||||||
|
return resolveFiles(builder, 'plugins/**/*.{js,ts}', app.dir)
|
||||||
|
.then(plugins => plugins.map((src) => {
|
||||||
|
return {
|
||||||
|
src,
|
||||||
|
mode: getPluginMode(src)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
@ -2,6 +2,7 @@ import { join, relative, dirname } from 'path'
|
|||||||
import fsExtra from 'fs-extra'
|
import fsExtra from 'fs-extra'
|
||||||
import globby from 'globby'
|
import globby from 'globby'
|
||||||
import lodashTemplate from 'lodash/template'
|
import lodashTemplate from 'lodash/template'
|
||||||
|
import * as nxt from './nxt'
|
||||||
|
|
||||||
export interface NuxtTemplate {
|
export interface NuxtTemplate {
|
||||||
src: string // Absolute path to source file
|
src: string // Absolute path to source file
|
||||||
@ -13,7 +14,8 @@ export function templateData (builder) {
|
|||||||
return {
|
return {
|
||||||
globals: builder.globals,
|
globals: builder.globals,
|
||||||
app: builder.app,
|
app: builder.app,
|
||||||
nuxtOptions: builder.nuxt.options
|
nuxtOptions: builder.nuxt.options,
|
||||||
|
nxt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user