1/* eslint-disable import/order */ 2const { copySync, removeSync } = require('fs-extra'); 3const merge = require('lodash/merge'); 4const { join } = require('path'); 5const semver = require('semver'); 6const { ESBuildPlugin } = require('esbuild-loader'); 7 8const navigation = require('./constants/navigation-data'); 9const versions = require('./constants/versions'); 10const { version, betaVersion } = require('./package.json'); 11 12// To generate a sitemap, we need context about the supported versions and navigational data 13const createSitemap = require('./scripts/create-sitemap'); 14 15// copy versions/v(latest version) to versions/latest 16// (Next.js only half-handles symlinks) 17const vLatest = join('pages', 'versions', `v${version}/`); 18const latest = join('pages', 'versions', 'latest/'); 19removeSync(latest); 20copySync(vLatest, latest); 21 22// Determine if we are using esbuild for MDX transpiling 23const enableEsbuild = !!process.env.USE_ESBUILD; 24 25console.log(enableEsbuild ? 'Using esbuild for MDX files' : 'Using babel for MDX files'); 26 27module.exports = { 28 trailingSlash: true, 29 // Rather than use `@zeit/next-mdx`, we replicate it 30 pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'md', 'mdx'], 31 webpack: (config, options) => { 32 // Add preval support for `constants/*` only and move it to the `.next/preval` cache. 33 // It's to prevent over-usage and separate the cache to allow manually invalidation. 34 // See: https://github.com/kentcdodds/babel-plugin-preval/issues/19 35 config.module.rules.push({ 36 test: /.jsx?$/, 37 include: [join(__dirname, 'constants')], 38 use: merge({}, options.defaultLoaders.babel, { 39 options: { 40 // Keep this path in sync with package.json and other scripts that clear the cache 41 cacheDirectory: '.next/preval', 42 plugins: ['preval'], 43 }, 44 }), 45 }); 46 47 // Add support for MDX with our custom loader and esbuild 48 config.module.rules.push({ 49 test: /.mdx?$/, // load both .md and .mdx files 50 use: [ 51 !enableEsbuild 52 ? options.defaultLoaders.babel 53 : { 54 loader: 'esbuild-loader', 55 options: { 56 loader: 'tsx', 57 target: 'es2017', 58 }, 59 }, 60 { 61 loader: '@mdx-js/loader', 62 options: { 63 remarkPlugins: [ 64 require('./mdx-plugins/remark-heading-meta'), 65 require('./mdx-plugins/remark-link-rewrite'), 66 ], 67 }, 68 }, 69 join(__dirname, './common/md-loader'), 70 ], 71 }); 72 // Fix inline or browser MDX usage: https://mdxjs.com/getting-started/webpack#running-mdx-in-the-browser 73 config.node = { fs: 'empty' }; 74 // Add the esbuild plugin only when using esbuild 75 if (enableEsbuild) { 76 config.plugins.push(new ESBuildPlugin()); 77 } 78 79 return config; 80 }, 81 // Create a map of all pages to export 82 async exportPathMap(defaultPathMap, { dev, outDir }) { 83 if (dev) { 84 return defaultPathMap; 85 } 86 const pathMap = Object.assign( 87 ...Object.entries(defaultPathMap).map(([pathname, page]) => { 88 if (pathname.match(/\/v[1-9][^/]*$/)) { 89 // ends in "/v<version>" 90 pathname += '/index.html'; // TODO: find out why we need to do this 91 } 92 if (pathname.match(/unversioned/)) { 93 return {}; 94 } else { 95 // hide versions greater than the package.json version number 96 const versionMatch = pathname.match(/\/v(\d\d\.\d\.\d)\//); 97 if ( 98 versionMatch && 99 versionMatch[1] && 100 semver.gt(versionMatch[1], betaVersion || version) 101 ) { 102 return {}; 103 } 104 return { [pathname]: page }; 105 } 106 }) 107 ); 108 // Create a sitemap for crawlers like Google and Algolia 109 createSitemap({ 110 pathMap, 111 domain: 'https://docs.expo.io', 112 output: join(outDir, 'sitemap.xml'), 113 // Some of the search engines only track the first N items from the sitemap, 114 // this makes sure our starting and general guides are first, and API index last (in order from new to old) 115 pathsPriority: [ 116 ...navigation.startingDirectories, 117 ...navigation.generalDirectories, 118 ...versions.VERSIONS.map(version => `versions/${version}`), 119 ], 120 // Some of our pages are "hidden" and should not be added to the sitemap 121 pathsHidden: navigation.previewDirectories, 122 }); 123 return pathMap; 124 }, 125}; 126