Skip to content

Commit

Permalink
Allow @babel/preset-typescript to be configured (vercel#11840)
Browse files Browse the repository at this point in the history
* Allow `@babel/preset-typescript` to be configured

Some usages, e.g. [getting parameter decorators to work properly](WarnerHooh/babel-plugin-parameter-decorator#19), require configuring `@babel/preset-typescript`.

This commit adds that functionality to `next/babel`.

* Add unit test for babel/preset allowing to pass options to @babel/preset-typescript

* Add integration test for onlyRemoveTypeImports

* Update babel dependencies

* Update to compatible typescript version and fix types

* Fix linting and run pre-nccing

* Update size-limit test

* Add additional tests

* Re-Apply delta to be calculated using -262

Co-authored-by: JJ Kasper <jj@jjsweb.site>
  • Loading branch information
2 people authored and rokinsky committed Jul 11, 2020
1 parent 86dbc66 commit eef5b66
Show file tree
Hide file tree
Showing 16 changed files with 941 additions and 501 deletions.
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ packages/react-refresh-utils/**/*.js
packages/react-refresh-utils/**/*.d.ts
packages/react-dev-overlay/lib/**
**/__tmp__/**
# prettier can't handle the `import type {} from ''` syntax yet
test/integration/typescript-only-remove-type-imports/**/*.ts
test/integration/typescript-only-remove-type-imports/**/*.tsx
lerna.json
3 changes: 3 additions & 0 deletions .prettierignore_staged
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@
**/_next/**
**/dist/**
packages/next/compiled/**/*
# prettier can't handle the `import type {} from ''` syntax yet
test/integration/typescript-only-remove-type-imports/**/*.ts
test/integration/typescript-only-remove-type-imports/**/*.tsx
lerna.json
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
"tailwindcss": "1.1.3",
"taskr": "1.1.0",
"tree-kill": "1.2.1",
"typescript": "3.7.3",
"typescript": "3.8.3",
"wait-port": "0.2.2",
"webpack-bundle-analyzer": "3.6.1"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/create-next-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"prompts": "2.1.0",
"rimraf": "3.0.0",
"tar": "4.4.10",
"typescript": "3.7.3",
"typescript": "3.8.3",
"update-check": "1.5.4",
"validate-npm-package-name": "3.0.0"
}
Expand Down
6 changes: 5 additions & 1 deletion packages/next/build/babel/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type NextBabelPresetOptions = {
'transform-runtime'?: any
'experimental-modern-preset'?: PluginItem
'styled-jsx'?: StyledJsxBabelOptions
'preset-typescript'?: any
}

type BabelPreset = {
Expand Down Expand Up @@ -116,7 +117,10 @@ module.exports = (
...options['preset-react'],
},
],
[require('@babel/preset-typescript'), { allowNamespaces: true }],
[
require('@babel/preset-typescript'),
{ allowNamespaces: true, ...options['preset-typescript'] },
],
],
plugins: [
[
Expand Down
35 changes: 18 additions & 17 deletions packages/next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,22 @@
},
"dependencies": {
"@ampproject/toolbox-optimizer": "2.3.1",
"@babel/core": "7.7.2",
"@babel/plugin-proposal-class-properties": "7.7.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.7.4",
"@babel/core": "7.9.0",
"@babel/plugin-proposal-class-properties": "7.8.3",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.8.3",
"@babel/plugin-proposal-numeric-separator": "7.8.3",
"@babel/plugin-proposal-object-rest-spread": "7.6.2",
"@babel/plugin-proposal-optional-chaining": "7.7.4",
"@babel/plugin-proposal-object-rest-spread": "7.9.5",
"@babel/plugin-proposal-optional-chaining": "7.9.0",
"@babel/plugin-syntax-bigint": "7.8.3",
"@babel/plugin-syntax-dynamic-import": "7.2.0",
"@babel/plugin-transform-modules-commonjs": "7.7.0",
"@babel/plugin-transform-runtime": "7.6.2",
"@babel/preset-env": "7.7.1",
"@babel/preset-modules": "0.1.1",
"@babel/preset-react": "7.7.0",
"@babel/preset-typescript": "7.7.2",
"@babel/runtime": "7.7.2",
"@babel/plugin-syntax-dynamic-import": "7.8.3",
"@babel/plugin-transform-modules-commonjs": "7.9.0",
"@babel/plugin-transform-runtime": "7.9.0",
"@babel/preset-env": "7.9.5",
"@babel/preset-modules": "0.1.3",
"@babel/preset-react": "7.9.4",
"@babel/preset-typescript": "7.9.0",
"@babel/runtime": "7.9.2",
"@babel/types": "7.9.5",
"@next/react-dev-overlay": "9.3.7-canary.16",
"@next/react-refresh-utils": "9.3.7-canary.16",
"babel-plugin-syntax-jsx": "6.18.0",
Expand Down Expand Up @@ -117,10 +118,10 @@
"@taskr/esnext": "1.1.0",
"@taskr/watch": "1.1.0",
"@types/amphtml-validator": "1.0.0",
"@types/babel__core": "7.1.3",
"@types/babel__generator": "7.6.0",
"@types/babel__core": "7.1.7",
"@types/babel__generator": "7.6.1",
"@types/babel__template": "7.0.2",
"@types/babel__traverse": "7.0.8",
"@types/babel__traverse": "7.0.10",
"@types/ci-info": "2.0.0",
"@types/compression": "0.0.36",
"@types/content-type": "1.1.3",
Expand Down Expand Up @@ -207,7 +208,7 @@
"terser-webpack-plugin": "gist:1b826e8b64f73158df99990d1b4624fa",
"text-table": "0.2.0",
"thread-loader": "2.1.3",
"typescript": "3.7.3",
"typescript": "3.8.3",
"unfetch": "4.1.0",
"unistore": "3.4.1",
"webpack-dev-middleware": "3.7.0",
Expand Down
2 changes: 1 addition & 1 deletion test/integration/size-limit/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe('Production response size', () => {
)

// These numbers are without gzip compression!
const delta = responseSizesBytes - 258 * 1024
const delta = responseSizesBytes - 262 * 1024
expect(delta).toBeLessThanOrEqual(1024) // don't increase size more than 1kb
expect(delta).toBeGreaterThanOrEqual(-1024) // don't decrease size more than 1kb without updating target
})
Expand Down
12 changes: 12 additions & 0 deletions test/integration/typescript-only-remove-type-imports/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"presets": [
[
"next/babel",
{
"preset-typescript": {
"onlyRemoveTypeImports": false
}
}
]
]
}
5 changes: 5 additions & 0 deletions test/integration/typescript-only-remove-type-imports/User.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface User {
id: string
username: string
email: string
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { User } from "./User";

export function getNewsletterRecipients(users: User[]) {
return users.map(u => u.email);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { User } from "../User";
// eslint-disable-next-line
import * as UnusedUserStatisticsThatShouldNotBeElided from "../UserStatistics";

const users: User[] = [
{
id: "a",
email: "a@a.de",
username: "anton"
},
{
id: "b",
email: "b@b.de",
username: "berta"
}
]

function Index() {
return (
<ul>
{users.map(u => (
<li key={u.id}>
{u.username}: {u.email}
</li>
))}
</ul>
);
}

export default Index;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default () => "A normal one"
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/* eslint-env jest */
/* global jasmine */
import { join } from 'path'
import {
nextBuild,
nextStart,
findPort,
killApp,
launchApp,
renderViaHTTP,
} from 'next-test-utils'

jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2

const appDir = join(__dirname, '../')
let app
let appPort

const runTests = () => {
it('should render a normal page correctly', async () => {
const html = await renderViaHTTP(appPort, '/normal')
expect(html).toContain('A normal one')
})

it('should render a page with type import correctly', async () => {
const html = await renderViaHTTP(appPort, '/')
expect(html).toContain('anton')
expect(html).toContain('berta')
})
}

describe('TypeScript onlyRemoveTypeImports', () => {
describe('production mode', () => {
beforeAll(async () => {
const { code } = await nextBuild(appDir)
if (code !== 0) throw new Error(`build failed with code ${code}`)
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(() => killApp(app))

runTests()
})

describe('dev mode', () => {
beforeAll(async () => {
appPort = await findPort()
app = await launchApp(appDir, appPort)
})
afterAll(() => killApp(app))

runTests()
})
})
19 changes: 19 additions & 0 deletions test/integration/typescript-only-remove-type-imports/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"compilerOptions": {
"esModuleInterop": true,
"module": "esnext",
"jsx": "preserve",
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true
},
"exclude": ["node_modules"],
"include": ["next-env.d.ts", "components", "pages"]
}
42 changes: 40 additions & 2 deletions test/unit/next-babel.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ process.env.NODE_ENV = 'production'
const preset = require('next/dist/build/babel/preset')
process.env.NODE_ENV = NODE_ENV

const babel = (code, esm = false, presetOptions = {}) =>
const babel = (code, esm = false, presetOptions = {}, filename = 'noop.js') =>
transform(code, {
filename: 'noop.js',
filename,
presets: [[preset, presetOptions]],
babelrc: false,
configFile: false,
Expand Down Expand Up @@ -136,6 +136,44 @@ describe('next/babel', () => {
})
})

describe('@babel/preset-typescript', () => {
describe('should allow passing options', () => {
const code = trim`
import { Tesla } from "./tesla";
import { Car } from "./car";
const benediktsDreamCar: Car = new Tesla();
`

function compileMyCar(options) {
return babel(
code,
false,
{
'preset-typescript': options,
},
'my-car.ts'
)
}

describe('when setting { onlyRemoveTypeImports: true }', () => {
it('should not elide import', () => {
const output = compileMyCar({ onlyRemoveTypeImports: true })

expect(output).toContain('require("./car")')
})
})

describe('when setting { onlyRemoveTypeImports: false }', () => {
it('should elide import', () => {
const output = compileMyCar({ onlyRemoveTypeImports: false })

expect(output).not.toContain('require("./car")')
})
})
})
})

describe('experimental-modern-preset', () => {
it('should allow passing a custom Babel preset', () => {
const code = trim`
Expand Down
Loading

0 comments on commit eef5b66

Please sign in to comment.