core.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /*!
  2. * @nuxt/core v2.15.8 (c) 2016-2021
  3. * Released under the MIT License
  4. * Repository: https://github.com/nuxt/nuxt.js
  5. * Website: https://nuxtjs.org
  6. */
  7. 'use strict';
  8. Object.defineProperty(exports, '__esModule', { value: true });
  9. const path = require('path');
  10. const fs = require('fs');
  11. const hash = require('hash-sum');
  12. const consola = require('consola');
  13. const utils = require('@nuxt/utils');
  14. const lodash = require('lodash');
  15. const Hookable = require('hable');
  16. const config = require('@nuxt/config');
  17. const server = require('@nuxt/server');
  18. const fs$1 = require('fs-extra');
  19. function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
  20. const path__default = /*#__PURE__*/_interopDefaultLegacy(path);
  21. const fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
  22. const hash__default = /*#__PURE__*/_interopDefaultLegacy(hash);
  23. const consola__default = /*#__PURE__*/_interopDefaultLegacy(consola);
  24. const Hookable__default = /*#__PURE__*/_interopDefaultLegacy(Hookable);
  25. const fs__default$1 = /*#__PURE__*/_interopDefaultLegacy(fs$1);
  26. class ModuleContainer {
  27. constructor (nuxt) {
  28. this.nuxt = nuxt;
  29. this.options = nuxt.options;
  30. this.requiredModules = {};
  31. // Self bind to allow destructre from container
  32. for (const method of Object.getOwnPropertyNames(ModuleContainer.prototype)) {
  33. if (typeof this[method] === 'function') {
  34. this[method] = this[method].bind(this);
  35. }
  36. }
  37. }
  38. async ready () {
  39. // Call before hook
  40. await this.nuxt.callHook('modules:before', this, this.options.modules);
  41. if (this.options.buildModules && !this.options._start) {
  42. // Load every devModule in sequence
  43. await utils.sequence(this.options.buildModules, this.addModule);
  44. }
  45. // Load every module in sequence
  46. await utils.sequence(this.options.modules, this.addModule);
  47. // Load ah-hoc modules last
  48. await utils.sequence(this.options._modules, this.addModule);
  49. // Call done hook
  50. await this.nuxt.callHook('modules:done', this);
  51. }
  52. addVendor () {
  53. consola__default['default'].warn('addVendor has been deprecated due to webpack4 optimization');
  54. }
  55. addTemplate (template) {
  56. if (!template) {
  57. throw new Error('Invalid template: ' + JSON.stringify(template))
  58. }
  59. // Validate & parse source
  60. const src = template.src || template;
  61. const srcPath = path__default['default'].parse(src);
  62. if (typeof src !== 'string' || !fs__default['default'].existsSync(src)) {
  63. throw new Error('Template src not found: ' + src)
  64. }
  65. // Mostly for DX, some people prefers `filename` vs `fileName`
  66. const fileName = template.fileName || template.filename;
  67. // Generate unique and human readable dst filename if not provided
  68. const dst = fileName || `${path__default['default'].basename(srcPath.dir)}.${srcPath.name}.${hash__default['default'](src)}${srcPath.ext}`;
  69. // Add to templates list
  70. const templateObj = {
  71. src,
  72. dst,
  73. options: template.options
  74. };
  75. this.options.build.templates.push(templateObj);
  76. return templateObj
  77. }
  78. addPlugin (template) {
  79. const { dst } = this.addTemplate(template);
  80. // Add to nuxt plugins
  81. this.options.plugins.unshift({
  82. src: path__default['default'].join(this.options.buildDir, dst),
  83. // TODO: remove deprecated option in Nuxt 3
  84. ssr: template.ssr,
  85. mode: template.mode
  86. });
  87. }
  88. addLayout (template, name) {
  89. const { dst, src } = this.addTemplate(template);
  90. const layoutName = name || path__default['default'].parse(src).name;
  91. const layout = this.options.layouts[layoutName];
  92. if (layout) {
  93. consola__default['default'].warn(`Duplicate layout registration, "${layoutName}" has been registered as "${layout}"`);
  94. }
  95. // Add to nuxt layouts
  96. this.options.layouts[layoutName] = `./${dst}`;
  97. // If error layout, set ErrorPage
  98. if (name === 'error') {
  99. this.addErrorLayout(dst);
  100. }
  101. }
  102. addErrorLayout (dst) {
  103. const relativeBuildDir = path__default['default'].relative(this.options.rootDir, this.options.buildDir);
  104. this.options.ErrorPage = `~/${relativeBuildDir}/${dst}`;
  105. }
  106. addServerMiddleware (middleware) {
  107. this.options.serverMiddleware.push(middleware);
  108. }
  109. extendBuild (fn) {
  110. this.options.build.extend = utils.chainFn(this.options.build.extend, fn);
  111. }
  112. extendRoutes (fn) {
  113. this.options.router.extendRoutes = utils.chainFn(
  114. this.options.router.extendRoutes,
  115. fn
  116. );
  117. }
  118. requireModule (moduleOpts, { paths } = {}) {
  119. return this.addModule(moduleOpts, undefined, { paths })
  120. }
  121. async addModule (moduleOpts, arg2, arg3) {
  122. // Arg2 was previously used for requireOnce which is ignored now
  123. const { paths } = { ...arg2, ...arg3 };
  124. let src;
  125. let options;
  126. let handler;
  127. // Type 1: String or Function
  128. if (typeof moduleOpts === 'string' || typeof moduleOpts === 'function') {
  129. src = moduleOpts;
  130. } else if (Array.isArray(moduleOpts)) {
  131. // Type 2: Babel style array
  132. [src, options] = moduleOpts;
  133. } else if (typeof moduleOpts === 'object') {
  134. // Type 3: Pure object
  135. ({ src, options, handler } = moduleOpts);
  136. }
  137. // Define handler if src is a function
  138. if (typeof src === 'function') {
  139. handler = src;
  140. }
  141. // Prevent adding buildModules-listed entries in production
  142. if (this.options.buildModules.includes(handler) && this.options._start) {
  143. return
  144. }
  145. // Resolve handler
  146. if (!handler) {
  147. try {
  148. handler = this.nuxt.resolver.requireModule(src, { paths });
  149. // pnp support
  150. try { (global.__NUXT_PATHS__ || []).push(this.nuxt.resolver.resolvePath(src, { paths })); } catch (_err) {}
  151. } catch (error) {
  152. if (error.code !== 'MODULE_NOT_FOUND') {
  153. throw error
  154. }
  155. // Hint only if entrypoint is not found and src is not local alias or path
  156. if (error.message.includes(src) && !/^[~.]|^@\//.test(src)) {
  157. let message = 'Module `{name}` not found.';
  158. if (this.options.buildModules.includes(src)) {
  159. message += ' Please ensure `{name}` is in `devDependencies` and installed. HINT: During build step, for npm/yarn, `NODE_ENV=production` or `--production` should NOT be used.'.replace('{name}', src);
  160. } else if (this.options.modules.includes(src)) {
  161. message += ' Please ensure `{name}` is in `dependencies` and installed.';
  162. }
  163. message = message.replace(/{name}/g, src);
  164. consola__default['default'].warn(message);
  165. }
  166. if (this.options._cli) {
  167. throw error
  168. } else {
  169. // TODO: Remove in next major version
  170. consola__default['default'].warn('Silently ignoring module as programatic usage detected.');
  171. return
  172. }
  173. }
  174. }
  175. // Validate handler
  176. if (typeof handler !== 'function') {
  177. throw new TypeError('Module should export a function: ' + src)
  178. }
  179. // Ensure module is required once
  180. const metaKey = handler.meta && handler.meta.name;
  181. const key = metaKey || src;
  182. if (typeof key === 'string') {
  183. if (this.requiredModules[key]) {
  184. if (!metaKey) {
  185. // TODO: Skip with nuxt3
  186. consola__default['default'].warn('Modules should be only specified once:', key);
  187. } else {
  188. return
  189. }
  190. }
  191. this.requiredModules[key] = { src, options, handler };
  192. }
  193. // Default module options to empty object
  194. if (options === undefined) {
  195. options = {};
  196. }
  197. const result = await handler.call(this, options);
  198. return result
  199. }
  200. }
  201. var version = "2.15.8";
  202. class Resolver {
  203. constructor (nuxt) {
  204. this.nuxt = nuxt;
  205. this.options = this.nuxt.options;
  206. // Binds
  207. this.resolvePath = this.resolvePath.bind(this);
  208. this.resolveAlias = this.resolveAlias.bind(this);
  209. this.resolveModule = this.resolveModule.bind(this);
  210. this.requireModule = this.requireModule.bind(this);
  211. this._createRequire = this.options.createRequire || utils.createRequire;
  212. this._require = this._createRequire(__filename);
  213. }
  214. resolveModule (path, { paths } = {}) {
  215. try {
  216. return this._require.resolve(path, {
  217. paths: [].concat(global.__NUXT_PREPATHS__ || [], paths || [], this.options.modulesDir, global.__NUXT_PATHS__ || [], process.cwd())
  218. })
  219. } catch (error) {
  220. if (error.code !== 'MODULE_NOT_FOUND') {
  221. throw error
  222. }
  223. }
  224. }
  225. resolveAlias (path$1) {
  226. if (utils.startsWithRootAlias(path$1)) {
  227. return path.join(this.options.rootDir, path$1.substr(2))
  228. }
  229. if (utils.startsWithSrcAlias(path$1)) {
  230. return path.join(this.options.srcDir, path$1.substr(1))
  231. }
  232. return path.resolve(this.options.srcDir, path$1)
  233. }
  234. resolvePath (path$1, { alias, isAlias = alias, module, isModule = module, isStyle, paths } = {}) {
  235. // TODO: Remove in Nuxt 3
  236. if (alias) {
  237. consola__default['default'].warn('Using alias is deprecated and will be removed in Nuxt 3. Use `isAlias` instead.');
  238. }
  239. if (module) {
  240. consola__default['default'].warn('Using module is deprecated and will be removed in Nuxt 3. Use `isModule` instead.');
  241. }
  242. // Fast return in case of path exists
  243. if (fs__default$1['default'].existsSync(path$1)) {
  244. return path$1
  245. }
  246. let resolvedPath;
  247. // Try to resolve it as a regular module
  248. if (isModule !== false) {
  249. resolvedPath = this.resolveModule(path$1, { paths });
  250. }
  251. // Try to resolve alias
  252. if (!resolvedPath && isAlias !== false) {
  253. resolvedPath = this.resolveAlias(path$1);
  254. }
  255. // Use path for resolvedPath
  256. if (!resolvedPath) {
  257. resolvedPath = path$1;
  258. }
  259. let isDirectory;
  260. // Check if resolvedPath exits and is not a directory
  261. if (fs__default$1['default'].existsSync(resolvedPath)) {
  262. isDirectory = fs__default$1['default'].lstatSync(resolvedPath).isDirectory();
  263. if (!isDirectory) {
  264. return resolvedPath
  265. }
  266. }
  267. const extensions = isStyle ? this.options.styleExtensions : this.options.extensions;
  268. // Check if any resolvedPath.[ext] or resolvedPath/index.[ext] exists
  269. for (const ext of extensions) {
  270. if (!isDirectory && fs__default$1['default'].existsSync(resolvedPath + '.' + ext)) {
  271. return resolvedPath + '.' + ext
  272. }
  273. const resolvedPathwithIndex = path.join(resolvedPath, 'index.' + ext);
  274. if (isDirectory && fs__default$1['default'].existsSync(resolvedPathwithIndex)) {
  275. return resolvedPathwithIndex
  276. }
  277. }
  278. // If there's no index.[ext] we just return the directory path
  279. if (isDirectory) {
  280. return resolvedPath
  281. }
  282. // Give up
  283. throw new Error(`Cannot resolve "${path$1}" from "${resolvedPath}"`)
  284. }
  285. requireModule (path, { alias, isAlias = alias, intropDefault, interopDefault = intropDefault, paths } = {}) {
  286. let resolvedPath = path;
  287. let requiredModule;
  288. // TODO: Remove in Nuxt 3
  289. if (intropDefault) {
  290. consola__default['default'].warn('Using intropDefault is deprecated and will be removed in Nuxt 3. Use `interopDefault` instead.');
  291. }
  292. if (alias) {
  293. consola__default['default'].warn('Using alias is deprecated and will be removed in Nuxt 3. Use `isAlias` instead.');
  294. }
  295. let lastError;
  296. // Try to resolve path
  297. try {
  298. resolvedPath = this.resolvePath(path, { isAlias, paths });
  299. } catch (e) {
  300. lastError = e;
  301. }
  302. const isExternal = utils.isExternalDependency(resolvedPath);
  303. // in dev mode make sure to clear the require cache so after
  304. // a dev server restart any changed file is reloaded
  305. if (this.options.dev && !isExternal) {
  306. utils.clearRequireCache(resolvedPath);
  307. }
  308. // Try to require
  309. try {
  310. requiredModule = this._require(resolvedPath);
  311. } catch (e) {
  312. lastError = e;
  313. }
  314. // Interop default
  315. if (interopDefault !== false && requiredModule && requiredModule.default) {
  316. requiredModule = requiredModule.default;
  317. }
  318. // Throw error if failed to require
  319. if (requiredModule === undefined && lastError) {
  320. throw lastError
  321. }
  322. return requiredModule
  323. }
  324. }
  325. class Nuxt extends Hookable__default['default'] {
  326. constructor (options = {}) {
  327. super(consola__default['default']);
  328. // Assign options and apply defaults
  329. this.options = config.getNuxtConfig(options);
  330. // Create instance of core components
  331. this.resolver = new Resolver(this);
  332. this.moduleContainer = new ModuleContainer(this);
  333. // Deprecated hooks
  334. this.deprecateHooks({
  335. // #3294 - 7514db73b25c23b8c14ebdafbb4e129ac282aabd
  336. 'render:context': {
  337. to: '_render:context',
  338. message: '`render:context(nuxt)` is deprecated, Please use `vue-renderer:ssr:context(context)`'
  339. },
  340. // #3773
  341. 'render:routeContext': {
  342. to: '_render:context',
  343. message: '`render:routeContext(nuxt)` is deprecated, Please use `vue-renderer:ssr:context(context)`'
  344. },
  345. showReady: 'webpack:done',
  346. // Introduced in 2.13
  347. 'export:done': 'generate:done',
  348. 'export:before': 'generate:before',
  349. 'export:extendRoutes': 'generate:extendRoutes',
  350. 'export:distRemoved': 'generate:distRemoved',
  351. 'export:distCopied': 'generate:distCopied',
  352. 'export:route': 'generate:route',
  353. 'export:routeFailed': 'generate:routeFailed',
  354. 'export:page': 'generate:page',
  355. 'export:routeCreated': 'generate:routeCreated'
  356. });
  357. // Add Legacy aliases
  358. utils.defineAlias(this, this.resolver, ['resolveAlias', 'resolvePath']);
  359. this.showReady = () => { this.callHook('webpack:done'); };
  360. // Init server
  361. if (this.options.server !== false) {
  362. this._initServer();
  363. }
  364. // Call ready
  365. if (this.options._ready !== false) {
  366. this.ready().catch((err) => {
  367. consola__default['default'].fatal(err);
  368. });
  369. }
  370. }
  371. static get version () {
  372. return `v${version}` + (global.__NUXT_DEV__ ? '-development' : '')
  373. }
  374. ready () {
  375. if (!this._ready) {
  376. this._ready = this._init();
  377. }
  378. return this._ready
  379. }
  380. async _init () {
  381. if (this._initCalled) {
  382. return this
  383. }
  384. this._initCalled = true;
  385. // Add hooks
  386. if (lodash.isPlainObject(this.options.hooks)) {
  387. this.addHooks(this.options.hooks);
  388. } else if (typeof this.options.hooks === 'function') {
  389. this.options.hooks(this.hook);
  390. }
  391. // Await for modules
  392. await this.moduleContainer.ready();
  393. // Await for server to be ready
  394. if (this.server) {
  395. await this.server.ready();
  396. }
  397. // Call ready hook
  398. await this.callHook('ready', this);
  399. return this
  400. }
  401. _initServer () {
  402. if (this.server) {
  403. return
  404. }
  405. this.server = new server.Server(this);
  406. this.renderer = this.server;
  407. this.render = this.server.app;
  408. utils.defineAlias(this, this.server, ['renderRoute', 'renderAndGetWindow', 'listen']);
  409. }
  410. async close (callback) {
  411. await this.callHook('close', this);
  412. if (typeof callback === 'function') {
  413. await callback();
  414. }
  415. this.clearHooks();
  416. }
  417. }
  418. const OVERRIDES = {
  419. dry: { dev: false, server: false },
  420. dev: { dev: true, _build: true },
  421. build: { dev: false, server: false, _build: true },
  422. start: { dev: false, _start: true }
  423. };
  424. async function loadNuxt (loadOptions) {
  425. // Normalize loadOptions
  426. if (typeof loadOptions === 'string') {
  427. loadOptions = { for: loadOptions };
  428. }
  429. const { ready = true } = loadOptions;
  430. const _for = loadOptions.for || 'dry';
  431. // Get overrides
  432. const override = OVERRIDES[_for];
  433. // Unsupported purpose
  434. if (!override) {
  435. throw new Error('Unsupported for: ' + _for)
  436. }
  437. // Load Config
  438. const config$1 = await config.loadNuxtConfig(loadOptions);
  439. // Apply config overrides
  440. Object.assign(config$1, override);
  441. // Initiate Nuxt
  442. const nuxt = new Nuxt(config$1);
  443. if (ready) {
  444. await nuxt.ready();
  445. }
  446. return nuxt
  447. }
  448. Object.defineProperty(exports, 'loadNuxtConfig', {
  449. enumerable: true,
  450. get: function () {
  451. return config.loadNuxtConfig;
  452. }
  453. });
  454. exports.Module = ModuleContainer;
  455. exports.Nuxt = Nuxt;
  456. exports.Resolver = Resolver;
  457. exports.loadNuxt = loadNuxt;