diff --git a/bin/next b/bin/next
index 72993ed9..884f19e5 100755
--- a/bin/next
+++ b/bin/next
@@ -88,6 +88,15 @@ const startProcess = () => {
let proc = startProcess()
+const wrapper = () => {
+ if (proc) {
+ proc.kill()
+ }
+}
+process.on('SIGINT', wrapper)
+process.on('SIGTERM', wrapper)
+process.on('exit', wrapper)
+
if (cmd === 'dev') {
const {watchFile} = require('fs')
watchFile(`${process.cwd()}/${CONFIG_FILE}`, (cur, prev) => {
diff --git a/build/webpack.js b/build/webpack.js
index ff5549ba..084258a4 100644
--- a/build/webpack.js
+++ b/build/webpack.js
@@ -137,7 +137,7 @@ export default async function getBaseWebpackConfig (dir: string, {dev = false, i
module: {
rules: [
dev && !isServer && {
- test: /\.(js|jsx)$/,
+ test: defaultLoaders.hotSelfAccept.options.extensions,
include: defaultLoaders.hotSelfAccept.options.include,
use: defaultLoaders.hotSelfAccept
},
diff --git a/package.json b/package.json
index 4d8d89de..7b737382 100644
--- a/package.json
+++ b/package.json
@@ -115,6 +115,7 @@
"@taskr/esnext": "1.1.0",
"@taskr/watch": "1.1.0",
"@zeit/next-css": "0.0.7",
+ "@zeit/next-typescript": "1.1.0",
"babel-eslint": "8.2.2",
"babel-jest": "21.2.0",
"babel-plugin-istanbul": "4.1.5",
diff --git a/test/integration/app-aspath/test/index.test.js b/test/integration/app-aspath/test/index.test.js
index 1b905416..a0471e3d 100644
--- a/test/integration/app-aspath/test/index.test.js
+++ b/test/integration/app-aspath/test/index.test.js
@@ -18,7 +18,7 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 5
describe('App asPath', () => {
beforeAll(async () => {
appPort = await findPort()
- server = await launchApp(join(__dirname, '../'), appPort, true)
+ server = await launchApp(join(__dirname, '../'), appPort)
// pre-build all pages at the start
await Promise.all([
diff --git a/test/integration/app-document/test/index.test.js b/test/integration/app-document/test/index.test.js
index 13cb8907..a073a191 100644
--- a/test/integration/app-document/test/index.test.js
+++ b/test/integration/app-document/test/index.test.js
@@ -19,7 +19,7 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 5
describe('Document and App', () => {
beforeAll(async () => {
context.appPort = await findPort()
- context.server = await launchApp(join(__dirname, '../'), context.appPort, true)
+ context.server = await launchApp(join(__dirname, '../'), context.appPort)
// pre-build all pages at the start
await Promise.all([
diff --git a/test/integration/babel/test/index.test.js b/test/integration/babel/test/index.test.js
index dc359a9a..653f49f6 100644
--- a/test/integration/babel/test/index.test.js
+++ b/test/integration/babel/test/index.test.js
@@ -18,7 +18,7 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 5
describe('Babel', () => {
beforeAll(async () => {
context.appPort = await findPort()
- context.server = await launchApp(join(__dirname, '../'), context.appPort, true)
+ context.server = await launchApp(join(__dirname, '../'), context.appPort)
// pre-build all pages at the start
await Promise.all([
diff --git a/test/integration/basic/test/index.test.js b/test/integration/basic/test/index.test.js
index d79a2684..9e5d9f8e 100644
--- a/test/integration/basic/test/index.test.js
+++ b/test/integration/basic/test/index.test.js
@@ -23,7 +23,7 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 5
describe('Basic Features', () => {
beforeAll(async () => {
context.appPort = await findPort()
- context.server = await launchApp(join(__dirname, '../'), context.appPort, true)
+ context.server = await launchApp(join(__dirname, '../'), context.appPort)
// pre-build all pages at the start
await Promise.all([
diff --git a/test/integration/config/test/index.test.js b/test/integration/config/test/index.test.js
index c21577d9..ef67229c 100644
--- a/test/integration/config/test/index.test.js
+++ b/test/integration/config/test/index.test.js
@@ -19,7 +19,7 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 5
describe('Configuration', () => {
beforeAll(async () => {
context.appPort = await findPort()
- context.server = await launchApp(join(__dirname, '../'), context.appPort, true)
+ context.server = await launchApp(join(__dirname, '../'), context.appPort)
// pre-build all pages at the start
await Promise.all([
diff --git a/test/integration/page-extensions/.babelrc b/test/integration/page-extensions/.babelrc
new file mode 100644
index 00000000..f1ced417
--- /dev/null
+++ b/test/integration/page-extensions/.babelrc
@@ -0,0 +1,6 @@
+{
+ "presets": [
+ "next/babel",
+ "@zeit/next-typescript/babel"
+ ]
+}
\ No newline at end of file
diff --git a/test/integration/page-extensions/next.config.js b/test/integration/page-extensions/next.config.js
new file mode 100644
index 00000000..eddd33b8
--- /dev/null
+++ b/test/integration/page-extensions/next.config.js
@@ -0,0 +1,7 @@
+const withTypescript = require('@zeit/next-typescript')
+module.exports = withTypescript({
+ onDemandEntries: {
+ // Make sure entries are not getting disposed.
+ maxInactiveAge: 1000 * 60 * 60
+ }
+})
diff --git a/test/integration/page-extensions/pages/hmr/some-page.tsx b/test/integration/page-extensions/pages/hmr/some-page.tsx
new file mode 100644
index 00000000..e283ec20
--- /dev/null
+++ b/test/integration/page-extensions/pages/hmr/some-page.tsx
@@ -0,0 +1,23 @@
+import React from 'react'
+
+if(typeof window !== 'undefined' && !window['HMR_RANDOM_NUMBER']) {
+ window['HMR_RANDOM_NUMBER'] = Math.random()
+}
+
+export default class Counter extends React.Component {
+ state = { count: 0 }
+
+ incr () {
+ const { count } = this.state
+ this.setState({ count: count + 1 })
+ }
+
+ render () {
+ return (
+
+
COUNT: {this.state.count}
+
+
+ )
+ }
+}
diff --git a/test/integration/page-extensions/test/.babelrc b/test/integration/page-extensions/test/.babelrc
new file mode 100644
index 00000000..27c7237a
--- /dev/null
+++ b/test/integration/page-extensions/test/.babelrc
@@ -0,0 +1,9 @@
+{
+ "presets": [
+ ["next/babel", {
+ "preset-env": {
+ "modules": "commonjs"
+ }
+ }]
+ ]
+}
\ No newline at end of file
diff --git a/test/integration/page-extensions/test/hmr.js b/test/integration/page-extensions/test/hmr.js
new file mode 100644
index 00000000..8b895666
--- /dev/null
+++ b/test/integration/page-extensions/test/hmr.js
@@ -0,0 +1,40 @@
+/* global describe, it, expect */
+import webdriver from 'next-webdriver'
+import { readFileSync, writeFileSync } from 'fs'
+import { join } from 'path'
+import { waitFor } from 'next-test-utils'
+
+export default (context, renderViaHTTP) => {
+ describe('Hot Module Reloading', () => {
+ it('should reload typescript file without refresh', async () => {
+ let browser
+ const pagePath = join(__dirname, '../', 'pages', 'hmr', 'some-page.tsx')
+
+ const originalContent = readFileSync(pagePath, 'utf8')
+ const editedContent = originalContent.replace('Increment', 'INCREMENT')
+ try {
+ browser = await webdriver(context.appPort, '/hmr/some-page')
+ const randomNumber = await browser.eval('window.HMR_RANDOM_NUMBER')
+ const originalButtonText = await browser.elementByCss('button').text()
+ expect(originalButtonText).toBe('Increment')
+
+ // Change the about.js page
+ writeFileSync(pagePath, editedContent, 'utf8')
+
+ // wait for 5 seconds
+ await waitFor(5000)
+
+ const randomNumberAfterEdit = await browser.eval('window.HMR_RANDOM_NUMBER')
+ expect(randomNumberAfterEdit).toBe(randomNumber)
+ const updatedButtonText = await browser.elementByCss('button').text()
+ expect(updatedButtonText).toBe('INCREMENT')
+ } finally {
+ // restore the about page content.
+ writeFileSync(pagePath, originalContent, 'utf8')
+ if (browser) {
+ browser.close()
+ }
+ }
+ })
+ })
+}
diff --git a/test/integration/page-extensions/test/index.test.js b/test/integration/page-extensions/test/index.test.js
new file mode 100644
index 00000000..ffe86afd
--- /dev/null
+++ b/test/integration/page-extensions/test/index.test.js
@@ -0,0 +1,30 @@
+/* global jasmine, describe, beforeAll, afterAll */
+
+import { join } from 'path'
+import {
+ renderViaHTTP,
+ findPort,
+ launchApp,
+ killApp
+} from 'next-test-utils'
+
+// test suits
+import hmr from './hmr'
+
+const context = {}
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 5
+
+describe('Page Extensions', () => {
+ beforeAll(async () => {
+ context.appPort = await findPort()
+ context.server = await launchApp(join(__dirname, '../'), context.appPort)
+
+ // pre-build all pages at the start
+ await Promise.all([
+ renderViaHTTP(context.appPort, '/hmr/some-page')
+ ])
+ })
+ afterAll(() => killApp(context.server))
+
+ hmr(context, (p, q) => renderViaHTTP(context.appPort, p, q))
+})
diff --git a/test/lib/next-test-utils.js b/test/lib/next-test-utils.js
index d2c54d46..e34cd8b3 100644
--- a/test/lib/next-test-utils.js
+++ b/test/lib/next-test-utils.js
@@ -113,7 +113,7 @@ export async function startApp (app) {
return server
}
-export async function stopApp (app) {
+export async function stopApp (server) {
if (server.__app) {
await server.__app.close()
}
diff --git a/yarn.lock b/yarn.lock
index 8d06a158..42385ccb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -349,6 +349,12 @@
dependencies:
"@babel/helper-plugin-utils" "7.0.0-beta.42"
+"@babel/plugin-syntax-typescript@7.0.0-beta.42":
+ version "7.0.0-beta.42"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.0.0-beta.42.tgz#ffc42945ca15e5ab369de6b9f5d9324499c623cf"
+ dependencies:
+ "@babel/helper-plugin-utils" "7.0.0-beta.42"
+
"@babel/plugin-transform-arrow-functions@7.0.0-beta.42":
version "7.0.0-beta.42"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0-beta.42.tgz#b918eb8760c38d6503a1a9858fa073786b60ab2b"
@@ -571,6 +577,13 @@
dependencies:
"@babel/helper-plugin-utils" "7.0.0-beta.42"
+"@babel/plugin-transform-typescript@7.0.0-beta.42":
+ version "7.0.0-beta.42"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.0.0-beta.42.tgz#e3a2d46014fd26e0729fd574b521fca4eb21144f"
+ dependencies:
+ "@babel/helper-plugin-utils" "7.0.0-beta.42"
+ "@babel/plugin-syntax-typescript" "7.0.0-beta.42"
+
"@babel/plugin-transform-unicode-regex@7.0.0-beta.42":
version "7.0.0-beta.42"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0-beta.42.tgz#1e7bdcf678d9a9066d06e6d334ab41ca11ca00ad"
@@ -641,6 +654,13 @@
"@babel/plugin-transform-react-jsx-self" "7.0.0-beta.42"
"@babel/plugin-transform-react-jsx-source" "7.0.0-beta.42"
+"@babel/preset-typescript@7.0.0-beta.42":
+ version "7.0.0-beta.42"
+ resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.0.0-beta.42.tgz#adb91d387a6eee7b45918de544d6c8fa122c2564"
+ dependencies:
+ "@babel/helper-plugin-utils" "7.0.0-beta.42"
+ "@babel/plugin-transform-typescript" "7.0.0-beta.42"
+
"@babel/runtime@7.0.0-beta.42":
version "7.0.0-beta.42"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0-beta.42.tgz#352e40c92e0460d3e82f49bd7e79f6cda76f919f"
@@ -751,6 +771,12 @@
postcss-loader "^2.0.10"
style-loader "^0.19.1"
+"@zeit/next-typescript@1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@zeit/next-typescript/-/next-typescript-1.1.0.tgz#57a45c85c336fee8d71c1bd966195565016932b2"
+ dependencies:
+ "@babel/preset-typescript" "7.0.0-beta.42"
+
abab@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e"