mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
parent
e43d21fdf0
commit
a9cf735f50
|
@ -1,8 +1,11 @@
|
|||
import {PluginObj} from '@babel/core'
|
||||
import {NodePath} from '@babel/traverse'
|
||||
import {ImportDeclaration} from '@babel/types'
|
||||
// Rewrite imports using next/<something> to next-server/<something>
|
||||
export default function ({ types: t, template }) {
|
||||
export default function NextToNextServer (): PluginObj {
|
||||
return {
|
||||
visitor: {
|
||||
ImportDeclaration (path) {
|
||||
ImportDeclaration (path: NodePath<ImportDeclaration>) {
|
||||
const source = path.node.source.value
|
||||
if (source === 'next/asset') {
|
||||
path.node.source.value = 'next-server/asset'
|
|
@ -23,10 +23,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWAR
|
|||
// Modified to put `webpack` and `modules` under `loadableGenerated` to be backwards compatible with next/dynamic which has a `modules` key
|
||||
// Modified to support `dynamic(import('something'))` and `dynamic(import('something'), options)
|
||||
|
||||
export default function ({ types: t, template }) {
|
||||
import {PluginObj} from '@babel/core'
|
||||
import {NodePath} from '@babel/traverse'
|
||||
import * as BabelTypes from '@babel/types'
|
||||
|
||||
export default function ({ types: t }: {types: typeof BabelTypes}): PluginObj {
|
||||
return {
|
||||
visitor: {
|
||||
ImportDeclaration (path) {
|
||||
ImportDeclaration (path: NodePath<BabelTypes.ImportDeclaration>) {
|
||||
let source = path.node.source.value
|
||||
if (source !== 'next/dynamic') return
|
||||
|
||||
|
@ -36,8 +40,12 @@ export default function ({ types: t, template }) {
|
|||
|
||||
if (!defaultSpecifier) return
|
||||
|
||||
let bindingName = defaultSpecifier.node.local.name
|
||||
let binding = path.scope.getBinding(bindingName)
|
||||
const bindingName = defaultSpecifier.node.local.name
|
||||
const binding = path.scope.getBinding(bindingName)
|
||||
|
||||
if(!binding) {
|
||||
return
|
||||
}
|
||||
|
||||
binding.referencePaths.forEach(refPath => {
|
||||
let callExpression = refPath.parentPath
|
||||
|
@ -53,20 +61,22 @@ export default function ({ types: t, template }) {
|
|||
if (!callExpression.isCallExpression()) return
|
||||
|
||||
let args = callExpression.get('arguments')
|
||||
if (args.length > 2) throw callExpression.error
|
||||
|
||||
let loader
|
||||
let options
|
||||
if (args.length > 2) {
|
||||
throw callExpression.buildCodeFrameError('next/dynamic only accepts 2 arguments')
|
||||
}
|
||||
|
||||
if (!args[0]) {
|
||||
return
|
||||
}
|
||||
|
||||
let loader
|
||||
let options
|
||||
|
||||
if (args[0].isObjectExpression()) {
|
||||
options = args[0]
|
||||
} else {
|
||||
if (!args[1]) {
|
||||
callExpression.pushContainer('arguments', t.objectExpression([]))
|
||||
callExpression.node.arguments.push(t.objectExpression([]))
|
||||
}
|
||||
// This is needed as the code is modified above
|
||||
args = callExpression.get('arguments')
|
||||
|
@ -77,10 +87,10 @@ export default function ({ types: t, template }) {
|
|||
if (!options.isObjectExpression()) return
|
||||
|
||||
let properties = options.get('properties')
|
||||
let propertiesMap = {}
|
||||
let propertiesMap: {[key: string]: NodePath<BabelTypes.ObjectProperty | BabelTypes.ObjectMethod | BabelTypes.SpreadProperty>} = {}
|
||||
|
||||
properties.forEach(property => {
|
||||
let key = property.get('key')
|
||||
const key: any = property.get('key')
|
||||
propertiesMap[key.node.name] = property
|
||||
})
|
||||
|
||||
|
@ -96,50 +106,50 @@ export default function ({ types: t, template }) {
|
|||
loader = propertiesMap.modules.get('value')
|
||||
}
|
||||
|
||||
let loaderMethod = loader
|
||||
let dynamicImports = []
|
||||
if(!loader || Array.isArray(loader)) {
|
||||
return
|
||||
}
|
||||
const dynamicImports: BabelTypes.StringLiteral[] = []
|
||||
|
||||
loaderMethod.traverse({
|
||||
loader.traverse({
|
||||
Import (path) {
|
||||
dynamicImports.push(path.parentPath)
|
||||
const args = path.parentPath.get('arguments')
|
||||
if(!Array.isArray(args)) return
|
||||
const node: any = args[0].node
|
||||
dynamicImports.push(node)
|
||||
}
|
||||
})
|
||||
|
||||
if (!dynamicImports.length) return
|
||||
|
||||
options.pushContainer(
|
||||
'properties',
|
||||
t.objectProperty(
|
||||
t.identifier('loadableGenerated'),
|
||||
t.objectExpression([
|
||||
t.objectProperty(
|
||||
t.identifier('webpack'),
|
||||
t.arrowFunctionExpression(
|
||||
[],
|
||||
t.arrayExpression(
|
||||
dynamicImports.map(dynamicImport => {
|
||||
return t.callExpression(
|
||||
t.memberExpression(
|
||||
t.identifier('require'),
|
||||
t.identifier('resolveWeak')
|
||||
),
|
||||
[dynamicImport.get('arguments')[0].node]
|
||||
)
|
||||
})
|
||||
)
|
||||
)
|
||||
),
|
||||
t.objectProperty(
|
||||
t.identifier('modules'),
|
||||
options.node.properties.push(t.objectProperty(
|
||||
t.identifier('loadableGenerated'),
|
||||
t.objectExpression([
|
||||
t.objectProperty(
|
||||
t.identifier('webpack'),
|
||||
t.arrowFunctionExpression(
|
||||
[],
|
||||
t.arrayExpression(
|
||||
dynamicImports.map(dynamicImport => {
|
||||
return dynamicImport.get('arguments')[0].node
|
||||
return t.callExpression(
|
||||
t.memberExpression(
|
||||
t.identifier('require'),
|
||||
t.identifier('resolveWeak')
|
||||
),
|
||||
[dynamicImport]
|
||||
)
|
||||
})
|
||||
)
|
||||
)
|
||||
])
|
||||
)
|
||||
)
|
||||
),
|
||||
t.objectProperty(
|
||||
t.identifier('modules'),
|
||||
t.arrayExpression(
|
||||
dynamicImports
|
||||
)
|
||||
)
|
||||
])
|
||||
))
|
||||
|
||||
// Turns `dynamic(import('something'))` into `dynamic(() => import('something'))` for backwards compat.
|
||||
// This is the replicate the behavior in versions below Next.js 7 where we magically handled not executing the `import()` too.
|
|
@ -1,63 +0,0 @@
|
|||
const env = process.env.NODE_ENV
|
||||
const isProduction = env === 'production'
|
||||
const isDevelopment = env === 'development'
|
||||
const isTest = env === 'test'
|
||||
|
||||
// Resolve styled-jsx plugins
|
||||
function styledJsxOptions (opts) {
|
||||
if (!opts) {
|
||||
return {}
|
||||
}
|
||||
|
||||
if (!Array.isArray(opts.plugins)) {
|
||||
return opts
|
||||
}
|
||||
|
||||
opts.plugins = opts.plugins.map(plugin => {
|
||||
if (Array.isArray(plugin)) {
|
||||
const [name, options] = plugin
|
||||
return [
|
||||
require.resolve(name),
|
||||
options
|
||||
]
|
||||
}
|
||||
|
||||
return require.resolve(plugin)
|
||||
})
|
||||
|
||||
return opts
|
||||
}
|
||||
|
||||
module.exports = (context, opts = {}) => ({
|
||||
presets: [
|
||||
[require('@babel/preset-env').default, {
|
||||
// In the test environment `modules` is often needed to be set to true, babel figures that out by itself using the `'auto'` option
|
||||
// In production/development this option is set to `false` so that webpack can handle import/export with tree-shaking
|
||||
modules: isDevelopment || isProduction ? false : 'auto',
|
||||
...opts['preset-env']
|
||||
}],
|
||||
[require('@babel/preset-react'), {
|
||||
// This adds @babel/plugin-transform-react-jsx-source and
|
||||
// @babel/plugin-transform-react-jsx-self automatically in development
|
||||
development: isDevelopment || isTest,
|
||||
...opts['preset-react']
|
||||
}]
|
||||
],
|
||||
plugins: [
|
||||
require('babel-plugin-react-require'),
|
||||
require('@babel/plugin-syntax-dynamic-import'),
|
||||
require('./plugins/react-loadable-plugin'),
|
||||
require('./plugins/next-to-next-server'),
|
||||
[require('@babel/plugin-proposal-class-properties'), opts['class-properties'] || {}],
|
||||
require('@babel/plugin-proposal-object-rest-spread'),
|
||||
[require('@babel/plugin-transform-runtime'), {
|
||||
corejs: 2,
|
||||
helpers: true,
|
||||
regenerator: true,
|
||||
useESModules: !isTest,
|
||||
...opts['transform-runtime']
|
||||
}],
|
||||
[require('styled-jsx/babel'), styledJsxOptions(opts['styled-jsx'])],
|
||||
process.env.NODE_ENV === 'production' && require('babel-plugin-transform-react-remove-prop-types')
|
||||
].filter(Boolean)
|
||||
})
|
84
packages/next/build/babel/preset.ts
Normal file
84
packages/next/build/babel/preset.ts
Normal file
|
@ -0,0 +1,84 @@
|
|||
import {PluginItem} from '@babel/core'
|
||||
const env = process.env.NODE_ENV
|
||||
const isProduction = env === 'production'
|
||||
const isDevelopment = env === 'development'
|
||||
const isTest = env === 'test'
|
||||
|
||||
type StyledJsxPlugin = [string, any] | string
|
||||
type StyledJsxBabelOptions = {
|
||||
plugins?: StyledJsxPlugin[]
|
||||
} | undefined
|
||||
|
||||
// Resolve styled-jsx plugins
|
||||
function styledJsxOptions (options: StyledJsxBabelOptions) {
|
||||
if (!options) {
|
||||
return {}
|
||||
}
|
||||
|
||||
if (!Array.isArray(options.plugins)) {
|
||||
return options
|
||||
}
|
||||
|
||||
options.plugins = options.plugins.map((plugin: StyledJsxPlugin): StyledJsxPlugin => {
|
||||
if (Array.isArray(plugin)) {
|
||||
const [name, options] = plugin
|
||||
return [
|
||||
require.resolve(name),
|
||||
options
|
||||
]
|
||||
}
|
||||
|
||||
return require.resolve(plugin)
|
||||
})
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
type NextBabelPresetOptions = {
|
||||
'preset-env'?: any,
|
||||
'preset-react'?: any,
|
||||
'class-properties'?: any,
|
||||
'transform-runtime'?: any,
|
||||
'styled-jsx'?: StyledJsxBabelOptions
|
||||
}
|
||||
|
||||
type BabelPreset = {
|
||||
presets?: PluginItem[] | null,
|
||||
plugins?: PluginItem[] | null
|
||||
}
|
||||
|
||||
module.exports = (context: any, options: NextBabelPresetOptions = {}): BabelPreset => {
|
||||
return {
|
||||
presets: [
|
||||
[require('@babel/preset-env').default, {
|
||||
// In the test environment `modules` is often needed to be set to true, babel figures that out by itself using the `'auto'` option
|
||||
// In production/development this option is set to `false` so that webpack can handle import/export with tree-shaking
|
||||
modules: isDevelopment || isProduction ? false : 'auto',
|
||||
...options['preset-env']
|
||||
}],
|
||||
[require('@babel/preset-react'), {
|
||||
// This adds @babel/plugin-transform-react-jsx-source and
|
||||
// @babel/plugin-transform-react-jsx-self automatically in development
|
||||
development: isDevelopment || isTest,
|
||||
...options['preset-react']
|
||||
}]
|
||||
],
|
||||
plugins: [
|
||||
require('babel-plugin-react-require'),
|
||||
require('@babel/plugin-syntax-dynamic-import'),
|
||||
require('./plugins/react-loadable-plugin'),
|
||||
require('./plugins/next-to-next-server'),
|
||||
[require('@babel/plugin-proposal-class-properties'), options['class-properties'] || {}],
|
||||
require('@babel/plugin-proposal-object-rest-spread'),
|
||||
[require('@babel/plugin-transform-runtime'), {
|
||||
corejs: 2,
|
||||
helpers: true,
|
||||
regenerator: true,
|
||||
useESModules: !isTest,
|
||||
...options['transform-runtime']
|
||||
}],
|
||||
[require('styled-jsx/babel'), styledJsxOptions(options['styled-jsx'])],
|
||||
process.env.NODE_ENV === 'production' && require('babel-plugin-transform-react-remove-prop-types')
|
||||
].filter(Boolean)
|
||||
}
|
||||
}
|
13
packages/next/build/generate-build-id.ts
Normal file
13
packages/next/build/generate-build-id.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
export async function generateBuildId (generate: () => string|null, fallback: () => string): Promise<string> {
|
||||
let buildId = await generate()
|
||||
// If there's no buildId defined we'll fall back
|
||||
if (buildId === null) {
|
||||
buildId = fallback()
|
||||
}
|
||||
|
||||
if (typeof buildId !== 'string') {
|
||||
throw new Error('generateBuildId did not return a string. https://err.sh/zeit/next.js/generatebuildid-not-a-string')
|
||||
}
|
||||
|
||||
return buildId.trim()
|
||||
}
|
|
@ -6,24 +6,11 @@ import nanoid from 'nanoid'
|
|||
import loadConfig from 'next-server/next-config'
|
||||
import { PHASE_PRODUCTION_BUILD, BUILD_ID_FILE } from 'next-server/constants'
|
||||
import getBaseWebpackConfig from './webpack'
|
||||
import {generateBuildId} from './generate-build-id'
|
||||
|
||||
const access = promisify(fs.access)
|
||||
const writeFile = promisify(fs.writeFile)
|
||||
|
||||
async function generateBuildId (generate, fallback) {
|
||||
let buildId = await generate()
|
||||
// If there's no buildId defined we'll fall back
|
||||
if (buildId === null) {
|
||||
buildId = fallback()
|
||||
}
|
||||
|
||||
if (typeof buildId !== 'string') {
|
||||
throw new Error('generateBuildId did not return a string. https://err.sh/zeit/next.js/generatebuildid-not-a-string')
|
||||
}
|
||||
|
||||
return buildId.trim()
|
||||
}
|
||||
|
||||
async function ensureProjectDirectoryIsWriteAble (dir) {
|
||||
try {
|
||||
await access(dir, (fs.constants || fs).W_OK)
|
||||
|
|
|
@ -94,6 +94,12 @@
|
|||
"@taskr/clear": "1.1.0",
|
||||
"@taskr/esnext": "1.1.0",
|
||||
"@taskr/watch": "1.1.0",
|
||||
"@types/babel__core": "7.0.4",
|
||||
"@types/babel__traverse": "7.0.3",
|
||||
"@types/nanoid": "1.2.0",
|
||||
"@types/babel-types": "7.0.4",
|
||||
"@types/babel__generator": "7.0.1",
|
||||
"@types/babel__template": "7.0.1",
|
||||
"taskr": "1.1.0",
|
||||
"typescript": "3.1.6"
|
||||
},
|
||||
|
|
|
@ -5,6 +5,17 @@
|
|||
"module": "esnext",
|
||||
"target": "ES2017",
|
||||
"esModuleInterop": true,
|
||||
"jsx": "react"
|
||||
"jsx": "react",
|
||||
"strictNullChecks": true,
|
||||
"noImplicitAny": true,
|
||||
"baseUrl": "../..",
|
||||
"paths": {
|
||||
"@babel/types": [
|
||||
"babel-types/index.d.ts",
|
||||
"@types/babel-types/index.d.ts",
|
||||
"node_modules/@types/babel-types/index.d.ts",
|
||||
"packages/next/node_modules/@types/babel-types/index.d.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue