Skip to content

Commit

Permalink
[v2] Update plugin-typescript to use Babel (#5709)
Browse files Browse the repository at this point in the history
* Update plugin-typescript to use Babel

* Fix code style

* Bump the version

* Update README

* Use npm for install instructions
  • Loading branch information
dennari authored and m-allanson committed Jun 6, 2018
1 parent 0d2740c commit 06175c4
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 237 deletions.
60 changes: 26 additions & 34 deletions packages/gatsby-plugin-typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ Provides drop-in support for TypeScript and TSX.

## Install

`npm install --save gatsby-plugin-typescript typescript`
`npm install gatsby-plugin-typescript`

## How to use

1. Include the plugin in your `gatsby-config.js` file.
1. Add `tsconfig.json` file on your root directory.
1. Write your components in TSX or TypeScript.
1. You're good to go.

Expand All @@ -19,37 +18,30 @@ Provides drop-in support for TypeScript and TSX.
plugins: [`gatsby-plugin-typescript`]
```

Or with optional configuration:
## Caveats

```javascript
plugins: [
{
resolve: "gatsby-plugin-typescript",
options: {
transpileOnly: true, // default
compilerOptions: {
target: `esnext`,
experimentalDecorators: true,
jsx: `react`,
}, // default
},
},
]
```
This plugin uses [`babel-plugin-transform-typescript`](https://new.babeljs.io/docs/en/next/babel-plugin-transform-typescript.html) to transpile typescript. It does _not do type checking_. Also since the TypeScript
compiler is not involved, the following applies:

`tsconfig.json`

```json
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "esnext",
"jsx": "react",
"lib": ["dom", "es2015", "es2017"]
},
"include": ["./src/**/*"]
}
```
> Does not support namespaces.
> Workaround: Move to using file exports, or
> migrate to using the module { } syntax instead.
>
> Does not support const enums because those require
> type information to compile. Workaround: Remove the
> const, which makes it available at runtime.
>
> Does not support export = and import =, because those
> cannot be compile to ES.next. Workaround: Convert
> to using export default and export const,
> and import x, {y} from "z".
https://new.babeljs.io/docs/en/next/babel-plugin-transform-typescript.html

## Type checking

First of all you should set up your IDE so that type errors are surfaced.
Visual Studio Code is very good in this regard.

In addition, you can see the instructions in [TypeScript-Babel-Starter](https://github.com/Microsoft/TypeScript-Babel-Starter)
for setting up a `type-check` task.
7 changes: 3 additions & 4 deletions packages/gatsby-plugin-typescript/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "gatsby-plugin-typescript",
"description": "Adds TypeScript support to Gatsby",
"version": "1.4.17-11",
"version": "2.0.0-alpha.1",
"author": "Kyle Mathews <[email protected]>",
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
Expand All @@ -10,10 +10,9 @@
"Noah Lange <[email protected]>"
],
"dependencies": {
"@babel/preset-typescript": "7.0.0-beta.47",
"@babel/runtime": "7.0.0-beta.47",
"babel-plugin-remove-graphql-queries": "^2.0.1-9",
"ts-loader": "^2.0.3",
"typescript": "^2.7.2"
"babel-plugin-remove-graphql-queries": "^2.0.1-9"
},
"devDependencies": {
"@babel/cli": "7.0.0-beta.47",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,21 @@ Array [
Object {
"test": /\\\\\\.tsx\\?\\$/,
"use": Array [
"babel-loader",
Object {
"loader": "/resolved/path/ts-loader",
"loader": "/resolved/path/babel-loader",
"options": Object {
"compilerOptions": Object {
"experimentalDecorators": true,
"jsx": "react",
"module": "es6",
"target": "esnext",
},
"transpileOnly": true,
"plugins": Array [
"babel-plugin-remove-graphql-queries",
],
"presets": Array [
Array [
"@babel/preset-env",
],
Array [
"@babel/preset-react",
],
"/resolved/path/@babel/preset-typescript",
],
},
},
],
Expand All @@ -29,17 +33,6 @@ Array [
]
`;

exports[`gatsby-plugin-typescript pre-processing transforms .ts files 1`] = `
"const now = moment().format('HH:MM:ss');
"
`;

exports[`gatsby-plugin-typescript pre-processing transforms JSX files 1`] = `
"import * as React from 'react';
export default () => React.createElement(\\"h1\\", null, \\"Hello World\\");
"
`;

exports[`gatsby-plugin-typescript returns correct extensions 1`] = `
Array [
".ts",
Expand Down
164 changes: 31 additions & 133 deletions packages/gatsby-plugin-typescript/src/__tests__/gatsby-node.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,48 @@
jest.mock(`../resolve`, () => module => `/resolved/path/${module}`)

const babelPluginRemoveQueries = require(`babel-plugin-remove-graphql-queries`)
.default
const {
resolvableExtensions,
onCreateWebpackConfig,
preprocessSource,
} = require(`../gatsby-node`)
const { tsPresetsFromJsPresets } = require(`../`)
const tsPresetPath = `/resolved/path/@babel/preset-typescript`
const jsOptions = {
options: {
presets: [
[`@babel/preset-env`],
[`@babel/preset-react`],
[`@babel/preset-flow`],
],
plugins: [`babel-plugin-remove-graphql-queries`],
},
loader: `/resolved/path/babel-loader`,
}

describe(`tsPresetsFromJsPresets`, () => {
it(`handles empty presets`, () => {
const presets = []
expect(tsPresetsFromJsPresets(presets)).toEqual([tsPresetPath])
})
it(`replaces preset-flow if it's last`, () => {
const presets = [`@babel/preset-flow`]
expect(tsPresetsFromJsPresets(presets)).toEqual([tsPresetPath])
})
it(`appends if preset-flow is not last`, () => {
const presets = [[`@babel/preset-flow`], [`@babel/preset-foo`]]
expect(tsPresetsFromJsPresets(presets)).toEqual(
presets.concat([tsPresetPath])
)
})
})

describe(`gatsby-plugin-typescript`, () => {
let args

function getLoader() {
const call = args.actions.setWebpackConfig.mock.calls[0]
return call[0].module.rules[0]
}

beforeEach(() => {
const actions = {
setWebpackConfig: jest.fn(),
}
const loaders = { js: jest.fn(() => `babel-loader`) }
const loaders = { js: jest.fn(() => jsOptions) }
args = { actions, loaders }
})

Expand All @@ -43,128 +65,4 @@ describe(`gatsby-plugin-typescript`, () => {
const lastCall = args.actions.setWebpackConfig.mock.calls.pop()
expect(lastCall).toMatchSnapshot()
})

// TODO: re-enable this test
it.skip(`adds the remove graphql queries plugin`, () => {
onCreateWebpackConfig(args, { compilerOptions: {} })

expect(args.loaders.js).toHaveBeenCalledTimes(1)
const lastCall = args.loaders.js.mock.calls.pop()

expect(lastCall[0]).toEqual({
plugins: [babelPluginRemoveQueries],
})
})

it(`passes the configuration to the ts-loader plugin`, () => {
const babelConfig = { plugins: [``] }
const config = {
loader: jest.fn(),
}
const options = { compilerOptions: { foo: `bar` }, transpileOnly: false }

onCreateWebpackConfig({ config, babelConfig, ...args }, options)

const expectedOptions = {
compilerOptions: {
target: `esnext`,
experimentalDecorators: true,
jsx: `react`,
foo: `bar`,
module: `es6`,
},
transpileOnly: false,
}

expect(getLoader()).toEqual({
test: /\.tsx?$/,
use: [
`babel-loader`,
{
loader: `/resolved/path/ts-loader`,
options: expectedOptions,
},
],
})
})

it(`uses default configuration for the ts-loader plugin when no config is provided`, () => {
const babelConfig = { plugins: [``] }
const config = {
loader: jest.fn(),
}
onCreateWebpackConfig(
{ config, babelConfig, ...args },
{ compilerOptions: {} }
)

const expectedOptions = {
compilerOptions: {
target: `esnext`,
experimentalDecorators: true,
jsx: `react`,
module: `es6`,
},
transpileOnly: true,
}

expect(getLoader()).toEqual({
test: /\.tsx?$/,
use: [
`babel-loader`,
{
loader: `/resolved/path/ts-loader`,
options: expectedOptions,
},
],
})
})

describe(`pre-processing`, () => {
const opts = { compilerOptions: {} }
it(`leaves non-tsx? files alone`, () => {
expect(
preprocessSource(
{
contents: `alert('hello');`,
filename: `test.js`,
},
opts
)
).toBeNull()
})

it(`transforms .ts files`, () => {
const js = preprocessSource(
{
filename: `index.ts`,
contents: `
declare let moment: any;
const now: string = moment().format('HH:MM:ss');
`,
},
opts
)
expect(js).not.toBeNull()
expect(js).toMatchSnapshot()
})

it(`transforms JSX files`, () => {
const js = preprocessSource(
{
filename: `tags.ts`,
contents: `
import * as React from 'react';
export default () => <h1>Hello World</h1>;
`,
},
opts
)

expect(js).not.toBeNull()
expect(js).toMatchSnapshot()
})
})
})
Loading

0 comments on commit 06175c4

Please sign in to comment.