模块目录
Nuxt 提供了高阶模块系统,可以扩展其核心功能。模块是在 Nuxt 启动时按顺序调用的函数。
探索 Nuxt 模块
查看 Nuxt 团队和社区创建的模块列表 ,以增强你的 Nuxt 项目:
- 165 个以上的模块
- 105 个以上的维护者
在使用 Nuxt 开发生产级应用程序时,可能会发现框架的核心功能不够用。Nuxt 可以通过配置选项和插件进行扩展,但在多个项目间维护这些自定义内容既繁琐又重复耗时。另一方面,如果开箱即用地支持所有项目需求,Nuxt 会变得非常复杂且难以使用。
这就是 Nuxt 引入更高阶模块系统以便轻松扩展核心功能的原因之一。模块是在 Nuxt 启动时按顺序调用的函数,框架会等待每个模块完成处理后再继续。这样,模块几乎可以自定义 Nuxt 的任何方面。得益于基于 webpack Tapable 的 Nuxt 模块设计,模块可以轻松地为特定入口点(如构建初始化)注册钩子。模块还可以覆盖模板、配置 webpack loader、添加 CSS 库以及执行许多其他有用的任务。
最棒的是,Nuxt 模块可以集成到 npm 包中,这样就可以在项目间复用并与社区共享,创建高质量插件的生态系统。
modules 属性
模块是 Nuxt 的扩展,可以扩展框架的核心功能并添加无限集成。安装模块后,可以将其添加到 nuxt.config.js 文件的 modules 属性中。
export default {
modules: [
// 使用包名
'@nuxtjs/axios',
// 相对于项目 srcDir 的路径
'~/modules/awesome.js',
// 提供选项
['@nuxtjs/google-analytics', { ua: 'X1234567' }],
// 内联定义
function () {}
]
}
Nuxt 会尝试使用 node 的加载路径(node_modules 中)解析模块数组中的每个元素。如果使用了 @ 别名,则从项目的 srcDir 解析。
模块应导出增强 nuxt 构建/运行时的函数,并可选择返回 promise 直到其工作完成。注意,如果依赖最新的 ES6 特性,需要预先转译,因为它们在运行时是必需的。
编写自己的模块
模块是函数,可以打包为 npm 模块或直接包含在项目源代码中。
export default {
exampleMsg: 'hello',
modules: [
// 简单用法
'~/modules/example',
// 直接传递选项
['~/modules/example', { token: '123' }]
]
}
export default function ExampleModule(moduleOptions) {
console.log(moduleOptions.token) // '123'
console.log(this.options.exampleMsg) // 'hello'
this.nuxt.hook('ready', async nuxt => {
console.log('Nuxt is ready')
})
}
// 将模块发布为 npm 包时必须
module.exports.meta = require('./package.json')
1) ModuleOptions
moduleOptions:这是模块使用者通过 modules 数组传递的对象,可以用它来自定义模块的行为。
顶层选项
在 nuxt.config.js 中注册模块时,有时在顶层使用选项会很方便,这样可以组合多个选项来源:
export default {
modules: [['@nuxtjs/axios', { anotherOption: true }]],
// axios 模块通过 `this.options.axios` 识别此选项
axios: {
option1,
option2
}
}
2) this.options
this.options:可以使用此引用直接访问 Nuxt 选项,这是分配了所有默认选项的用户 nuxt.config.js 内容,可用于模块间的共享选项。
export default function (moduleOptions) {
// `options` 包含 option1、option2 和 anotherOption
const options = Object.assign({}, this.options.axios, moduleOptions)
// ...
}
添加 CSS 库
如果模块提供 CSS 库,请检查用户是否已包含该库以避免重复,并添加禁用模块中 CSS 库的选项:
export default function (moduleOptions) {
if (moduleOptions.fontAwesome !== false) {
// 添加 Font Awesome
this.options.css.push('font-awesome/css/font-awesome.css')
}
}
输出资源
可以注册 webpack 插件在构建期间输出资源:
export default function (moduleOptions) {
const info = 'Built by awesome module - 1.3 alpha on ' + Date.now()
this.options.build.plugins.push({
apply(compiler) {
compiler.plugin('emit', (compilation, cb) => {
// 这会生成包含 info 变量内容的 `.nuxt/dist/info.txt`
// 源也可以是 buffer
compilation.assets['info.txt'] = {
source: () => info,
size: () => info.length
}
cb()
})
}
})
}
3) this.nuxt
this.nuxt:这是对当前 Nuxt 实例的引用,可以在特定生命周期事件上注册钩子。
- Ready:Nuxt 准备好工作(ModuleContainer 和 Renderer 准备就绪)。
nuxt.hook('ready', async nuxt => {
// 在此处编写自定义代码
})
- Error:调用钩子时未捕获的错误。
nuxt.hook('error', async error => {
// 在此处编写自定义代码
})
- Close:Nuxt 实例正常关闭。
nuxt.hook('close', async nuxt => {
// 在此处编写自定义代码
})
- Listen:Nuxt 内部服务器开始监听(使用 nuxt start 或 nuxt dev)
nuxt.hook('listen', async (server, { host, port }) => {
// 在此处编写自定义代码
})
this:模块的上下文,所有模块都在 ModuleContainer 实例的上下文中调用。
有关可用方法,请参阅 ModuleContainer 类文档。
在特定钩子上运行任务
模块可能不仅需要在 Nuxt 初始化时执行,有时只需要在特定条件下执行。可以使用强大的 Nuxt 钩子在特定事件上执行任务(基于 Hookable )。Nuxt 会等待函数返回 Promise 或定义为 async 的函数。
以下是一些基本示例:
export default function myModule() {
this.nuxt.hook('modules:done', moduleContainer => {
// 所有模块加载完成时调用
})
this.nuxt.hook('render:before', renderer => {
// 创建渲染器后调用
})
this.nuxt.hook('build:compile', async ({ name, compiler }) => {
// 编译器(默认:webpack)启动前调用
})
this.nuxt.hook('generate:before', async generator => {
// Nuxt 生成页面前调用
})
}
提供插件
模块添加后,通常会提供一个或多个插件。例如,bootstrap-vue 模块需要将自身注册到 Vue 中,这种情况下可以使用 this.addPlugin 助手。
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue/dist/bootstrap-vue.esm'
Vue.use(BootstrapVue)
import path from 'path'
export default function nuxtBootstrapVue(moduleOptions) {
// 注册 `plugin.js` 模板
this.addPlugin(path.resolve(__dirname, 'plugin.js'))
}
注意: 模块注入的插件会添加到插件列表的开头。可选方案:
-
手动将插件添加到插件列表末尾(
this.nuxt.options.plugins.push(...) - 如果依赖其他模块,则反转模块顺序
模板插件
已注册的模板和插件可以利用 lodash 模板 有条件地更改已注册插件的输出。
// 设置 Google Analytics UA
ga('create', '<%= options.ua %>', 'auto')
<% if (options.debug) { %>
// 仅开发用代码
<% } %>
import path from 'path'
export default function nuxtGoogleAnalytics(moduleOptions) {
// 注册 `plugin.js` 模板
this.addPlugin({
src: path.resolve(__dirname, 'plugin.js'),
options: {
// 将插件复制到项目时,Nuxt 会将 `options.ua` 替换为 `123`
ua: 123,
// 包含 dev 的条件部分会从生产构建的插件代码中删除
debug: this.options.dev
}
})
}
注册自定义 webpack loader
可以使用 this.extendBuild 实现与 nuxt.config.js 中 build.extend 相同的功能。
export default function (moduleOptions) {
this.extendBuild((config, { isClient, isServer }) => {
// `.foo` loader
config.module.rules.push({
test: /\.foo$/,
use: [...]
})
// 自定义现有 loader
// 参阅 Nuxt 内部源代码:
// https://github.com/nuxt/nuxt/blob/2.x-dev/packages/webpack/src/config/base.js
const barLoader = config.module.rules.find(rule => rule.loader === 'bar-loader')
})
}
异步模块
并非所有模块都会同步执行所有操作,例如可能想开发一个需要从 API 获取数据或执行异步操作的模块。为此,Nuxt 支持可以返回 Promise 或调用回调的异步模块。
使用 async/await
import fse from 'fs-extra'
export default async function asyncModule() {
// 可以在此处使用 `async`/`await` 进行异步操作
const pages = await fse.readJson('./pages.json')
}
返回 Promise
export default function asyncModule($http) {
return $http
.get('https://jsonplaceholder.typicode.com/users')
.then(res => res.data.map(user => '/users/' + user.username))
.then(routes => {
// 通过扩展 Nuxt 路由做些什么
})
}
发布模块
module.exports.meta:将模块发布为 npm 包时需要此行。Nuxt 内部使用 meta 来更好地处理包。
module.exports.meta = require('./package.json')
buildModules
某些模块只在开发和构建时导入。使用 buildModules 可以加快生产环境启动速度,并显著减少生产环境 node_modules 的大小。请参阅各模块文档,了解推荐使用 modules 还是 buildModules。
使用方式的区别:
-
在
nuxt.config.js中使用buildModules代替modules
export default {
buildModules: ['@nuxtjs/eslint-module']
}
-
在
package.json中使用devDependencies代替dependencies
yarn add --dev @nuxtjs/eslint-module
npm install --save-dev @nuxtjs/eslint-module
devDependency,并在 nuxt.config.js 中使用 buildModules 代替 modules。以下情况除外,模块应为 buildModule:
- 提供 serverMiddleware
- 需要注册 Node.js 运行时钩子(如 Sentry)
-
影响 vue-renderer 行为或使用
server:或vue-renderer:命名空间的钩子 - webpack 范围之外的其他内容(提示:插件和模板会被编译,在 webpack 范围内)
buildModules 提供时,请注意此功能从 Nuxt v2.9 起可用。老用户需要升级 Nuxt 或使用 modules 部分。