Skip to content

Commit

Permalink
Remove deprecated features (#25446)
Browse files Browse the repository at this point in the history
* Remove deprecated features

In the next major version we'll want to merge this PR that removes some of the long-time deprecated features, it'll have a positive effect on bundle size.

* Update tests

* Update tests

* Change unsized to layout=fill in test

* Update sizes

* Update rotation test

* Update size limit test

* Update test

* Update test

* Update test
  • Loading branch information
timneutkens committed Jun 2, 2021
1 parent d27cbf0 commit ed3e8f7
Show file tree
Hide file tree
Showing 22 changed files with 171 additions and 689 deletions.
32 changes: 32 additions & 0 deletions docs/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,38 @@ description: Learn how to upgrade Next.js.

# Upgrade Guide

## Upgrading from version 10 to 11

### Remove `super.componentDidCatch()` from `pages/_app.js`

The `next/app` component's `componentDidCatch` has been deprecated since Next.js 9 as it's no longer needed and has since been a no-op, in Next.js 11 it has been removed.

If your `pages/_app.js` has a custom `componentDidCatch` method you can remove `super.componentDidCatch` as it is no longer needed.

### Remove `Container` from `pages/_app.js`

This export has been deprecated since Next.js 9 as it's no longer needed and has since been a no-op with a warning during development. In Next.js 11 it has been removed.

If your `pages/_app.js` imports `Container` from `next/app` you can remove `Container` as it has been removed. Learn more in [the documentation](https://nextjs.org/docs/messages/app-container-deprecated).

### Remove `props.url` usage from page components

This property has been deprecated since Next.js 4 and has since shown a warning during development. With the introduction of `getStaticProps` / `getServerSideProps` these methods already disallowed usage of `props.url`. In Next.js 11 it has been removed completely.

You can learn more in [the documentation](https://nextjs.org/docs/messages/url-deprecated).

### Remove `unsized` property on `next/image`

The `unsized` property on `next/image` was deprecated in Next.js 10.0.1. You can use `layout="fill"` instead. In Next.js 11 `unsized` was removed.

### Remove `modules` property on `next/dynamic`

The `modules` and `render` option for `next/dynamic` have been deprecated since Next.js 9.5 showing a warning that it has been deprecated. This was done in order to make `next/dynamic` close to `React.lazy` in API surface. In Next.js 11 the `modules` and `render` options have been removed.

This option hasn't been mentioned in the documentation since Next.js 8 so it's less likely that your application is using it.

If you application does use `modules` and `render` you can refer to [the documentation](https://nextjs.org/docs/messages/next-dynamic-modules).

## React 16 to 17

React 17 introduced a new [JSX Transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) that brings a long-time Next.js feature to the wider React ecosystem: Not having to `import React from 'react'` when using JSX. When using React 17 Next.js will automatically use the new transform. This transform does not make the `React` variable global, which was an unintended side-effect of the previous Next.js implementation. A [codemod is available](/docs/advanced-features/codemods.md#add-missing-react-import) to automatically fix cases where you accidentally used `React` without importing it.
Expand Down
23 changes: 1 addition & 22 deletions packages/next/client/image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,6 @@ export type ImageProps = Omit<
objectFit?: ImgElementStyle['objectFit']
objectPosition?: ImgElementStyle['objectPosition']
} & (
| {
width?: never
height?: never
/** @deprecated Use `layout="fill"` instead */
unsized: true
}
| { width?: never; height?: never; layout: 'fill' }
| {
width: number | string
Expand Down Expand Up @@ -260,12 +254,7 @@ export default function Image({
}: ImageProps) {
let rest: Partial<ImageProps> = all
let layout: NonNullable<LayoutValue> = sizes ? 'responsive' : 'intrinsic'
let unsized = false
if ('unsized' in rest) {
unsized = Boolean(rest.unsized)
// Remove property so it's not spread into image:
delete rest['unsized']
} else if ('layout' in rest) {
if ('layout' in rest) {
// Override default layout if the user specified one:
if (rest.layout) layout = rest.layout

Expand Down Expand Up @@ -304,11 +293,6 @@ export default function Image({
`Image with src "${src}" has both "priority" and "loading='lazy'" properties. Only one should be used.`
)
}
if (unsized) {
throw new Error(
`Image with src "${src}" has deprecated "unsized" property, which was removed in favor of the "layout='fill'" property`
)
}
}

let isLazy =
Expand Down Expand Up @@ -461,11 +445,6 @@ export default function Image({
})
}

if (unsized) {
wrapperStyle = undefined
sizerStyle = undefined
imgStyle = undefined
}
return (
<div style={wrapperStyle}>
{sizerStyle ? (
Expand Down
45 changes: 2 additions & 43 deletions packages/next/next-server/lib/dynamic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,9 @@ export type LoadableBaseOptions<P = {}> = LoadableGeneratedOptions & {
ssr?: boolean
}

export type LoadableOptions<P = {}> = LoadableBaseOptions<P> & {
render?(loader: any, props: any): JSX.Element
}
export type LoadableOptions<P = {}> = LoadableBaseOptions<P>

export type DynamicOptions<P = {}> = LoadableBaseOptions<P> & {
/**
* @deprecated the modules option has been planned for removal
*/
render?(props: P, loaded: any): JSX.Element
}
export type DynamicOptions<P = {}> = LoadableBaseOptions<P>

export type LoadableFn<P = {}> = (
opts: LoadableOptions<P>
Expand Down Expand Up @@ -117,40 +110,6 @@ export default function dynamic<P = {}>(
// Support for passing options, eg: dynamic(import('../hello-world'), {loading: () => <p>Loading something</p>})
loadableOptions = { ...loadableOptions, ...options }

if (
typeof dynamicOptions === 'object' &&
!(dynamicOptions instanceof Promise)
) {
// show deprecation warning for `modules` key in development
if (process.env.NODE_ENV !== 'production') {
if (dynamicOptions.modules) {
console.warn(
'The modules option for next/dynamic has been deprecated. See here for more info https://nextjs.org/docs/messages/next-dynamic-modules'
)
}
}
// Support for `render` when using a mapping, eg: `dynamic({ modules: () => {return {HelloWorld: import('../hello-world')}, render(props, loaded) {} } })
if (dynamicOptions.render) {
loadableOptions.render = (loaded, props) =>
dynamicOptions.render!(props, loaded)
}
// Support for `modules` when using a mapping, eg: `dynamic({ modules: () => {return {HelloWorld: import('../hello-world')}, render(props, loaded) {} } })
if (dynamicOptions.modules) {
loadableFn = Loadable.Map
const loadModules: LoaderMap = {}
const modules = dynamicOptions.modules()
Object.keys(modules).forEach((key) => {
const value: any = modules[key]
if (typeof value.then === 'function') {
loadModules[key] = () => value.then((mod: any) => mod.default || mod)
return
}
loadModules[key] = value
})
loadableOptions.loader = loadModules
}
}

// coming from build/babel/plugins/react-loadable-plugin.js
if (loadableOptions.loadableGenerated) {
loadableOptions = {
Expand Down
64 changes: 1 addition & 63 deletions packages/next/next-server/lib/loadable.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,69 +53,17 @@ function load(loader) {
return state
}

function loadMap(obj) {
let state = {
loading: false,
loaded: {},
error: null,
}

let promises = []

try {
Object.keys(obj).forEach((key) => {
let result = load(obj[key])

if (!result.loading) {
state.loaded[key] = result.loaded
state.error = result.error
} else {
state.loading = true
}

promises.push(result.promise)

result.promise
.then((res) => {
state.loaded[key] = res
})
.catch((err) => {
state.error = err
})
})
} catch (err) {
state.error = err
}

state.promise = Promise.all(promises)
.then((res) => {
state.loading = false
return res
})
.catch((err) => {
state.loading = false
throw err
})

return state
}

function resolve(obj) {
return obj && obj.__esModule ? obj.default : obj
}

function render(loaded, props) {
return React.createElement(resolve(loaded), props)
}

function createLoadableComponent(loadFn, options) {
let opts = Object.assign(
{
loader: null,
loading: null,
delay: 200,
timeout: null,
render: render,
webpack: null,
modules: null,
},
Expand Down Expand Up @@ -188,7 +136,7 @@ function createLoadableComponent(loadFn, options) {
retry: subscription.retry,
})
} else if (state.loaded) {
return opts.render(state.loaded, props)
return React.createElement(resolve(state.loaded), props)
} else {
return null
}
Expand Down Expand Up @@ -291,16 +239,6 @@ function Loadable(opts) {
return createLoadableComponent(load, opts)
}

function LoadableMap(opts) {
if (typeof opts.render !== 'function') {
throw new Error('LoadableMap requires a `render(loaded, props)` function')
}

return createLoadableComponent(loadMap, opts)
}

Loadable.Map = LoadableMap

function flushInitializers(initializers, ids) {
let promises = []

Expand Down
92 changes: 3 additions & 89 deletions packages/next/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { ErrorInfo } from 'react'
import React from 'react'
import {
execOnce,
loadGetInitialProps,
AppContextType,
AppInitialProps,
Expand Down Expand Up @@ -36,94 +35,9 @@ export default class App<P = {}, CP = {}, S = {}> extends React.Component<
static origGetInitialProps = appGetInitialProps
static getInitialProps = appGetInitialProps

// Kept here for backwards compatibility.
// When someone ended App they could call `super.componentDidCatch`.
// @deprecated This method is no longer needed. Errors are caught at the top level
componentDidCatch(error: Error, _errorInfo: ErrorInfo): void {
throw error
}

render() {
const { router, Component, pageProps, __N_SSG, __N_SSP } = this
.props as AppProps<CP>

return (
<Component
{...pageProps}
{
// we don't add the legacy URL prop if it's using non-legacy
// methods like getStaticProps and getServerSideProps
...(!(__N_SSG || __N_SSP) ? { url: createUrl(router) } : {})
}
/>
)
}
}

let warnContainer: () => void
let warnUrl: () => void

if (process.env.NODE_ENV !== 'production') {
warnContainer = execOnce(() => {
console.warn(
`Warning: the \`Container\` in \`_app\` has been deprecated and should be removed. https://nextjs.org/docs/messages/app-container-deprecated`
)
})

warnUrl = execOnce(() => {
console.error(
`Warning: the 'url' property is deprecated. https://nextjs.org/docs/messages/url-deprecated`
)
})
}

// @deprecated noop for now until removal
export function Container(p: any) {
if (process.env.NODE_ENV !== 'production') warnContainer()
return p.children
}

export function createUrl(router: Router) {
// This is to make sure we don't references the router object at call time
const { pathname, asPath, query } = router
return {
get query() {
if (process.env.NODE_ENV !== 'production') warnUrl()
return query
},
get pathname() {
if (process.env.NODE_ENV !== 'production') warnUrl()
return pathname
},
get asPath() {
if (process.env.NODE_ENV !== 'production') warnUrl()
return asPath
},
back: () => {
if (process.env.NODE_ENV !== 'production') warnUrl()
router.back()
},
push: (url: string, as?: string) => {
if (process.env.NODE_ENV !== 'production') warnUrl()
return router.push(url, as)
},
pushTo: (href: string, as?: string) => {
if (process.env.NODE_ENV !== 'production') warnUrl()
const pushRoute = as ? href : ''
const pushUrl = as || href

return router.push(pushRoute, pushUrl)
},
replace: (url: string, as?: string) => {
if (process.env.NODE_ENV !== 'production') warnUrl()
return router.replace(url, as)
},
replaceTo: (href: string, as?: string) => {
if (process.env.NODE_ENV !== 'production') warnUrl()
const replaceRoute = as ? href : ''
const replaceUrl = as || href
const { Component, pageProps } = this.props as AppProps<CP>

return router.replace(replaceRoute, replaceUrl)
},
return <Component {...pageProps} />
}
}
Loading

0 comments on commit ed3e8f7

Please sign in to comment.