From 4faf10edbc144108906f7c9f2d3a45c9d249caf8 Mon Sep 17 00:00:00 2001 From: Swashata Ghosh Date: Mon, 22 Oct 2018 15:10:03 +0530 Subject: [PATCH] feat: add ts checker webpack plugin Only when tsconfig.json is found in the project. See #15 --- .../plugin/inc/class-wpackio-plugin-init.php | 1 + examples/plugin/package.json | 4 +- examples/plugin/src/ts/main.ts | 14 +++++++ examples/plugin/src/ts/module.ts | 3 ++ examples/plugin/tsconfig.json | 17 ++++++++ examples/plugin/wpackio.project.js | 6 +++ .../config/WebpackConfigHelper.spec.ts | 18 ++++++++ packages/scripts/package.json | 1 + .../scripts/src/config/WebpackConfigHelper.ts | 28 +++++++++++++ site/src/pages/index.js | 6 ++- yarn.lock | 41 ++++++++++++++++++- 11 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 examples/plugin/src/ts/main.ts create mode 100644 examples/plugin/src/ts/module.ts create mode 100644 examples/plugin/tsconfig.json diff --git a/examples/plugin/inc/class-wpackio-plugin-init.php b/examples/plugin/inc/class-wpackio-plugin-init.php index 63d88b38e..1ad72bd12 100644 --- a/examples/plugin/inc/class-wpackio-plugin-init.php +++ b/examples/plugin/inc/class-wpackio-plugin-init.php @@ -20,6 +20,7 @@ function plugin_enqueue() { $this->enqueue->enqueue( 'app', 'main', [] ); $this->enqueue->enqueue( 'app', 'mobile', [] ); $this->enqueue->enqueue( 'foo', 'main', [] ); + $this->enqueue->enqueue( 'tsapp', 'main', [] ); } function reactapp( $atts, $content = null ) { diff --git a/examples/plugin/package.json b/examples/plugin/package.json index 356621296..e76f6ba89 100644 --- a/examples/plugin/package.json +++ b/examples/plugin/package.json @@ -8,7 +8,8 @@ "private": true, "devDependencies": { "autoprefixer": "^9.1.5", - "node-sass": "^4.9.3" + "node-sass": "^4.9.3", + "typescript": "^3.1.3" }, "scripts": { "bootstrap": "wpackio-scripts bootstrap", @@ -16,6 +17,7 @@ "exbuild": "wpackio-scripts build" }, "dependencies": { + "@types/webpack-env": "^1.13.6", "@wpackio/scripts": "^1.2.1", "react": "^16.5.2", "react-bootstrap": "^1.0.0-beta.1", diff --git a/examples/plugin/src/ts/main.ts b/examples/plugin/src/ts/main.ts new file mode 100644 index 000000000..60dbda46c --- /dev/null +++ b/examples/plugin/src/ts/main.ts @@ -0,0 +1,14 @@ +/// + +import { strRepeat } from './module'; + +console.log(strRepeat('foo', 10)); +console.log(strRepeat('foo', 10)); +console.log(strRepeat('foo', 10)); + +if (module.hot) { + module.hot.accept('./module.ts', () => { + const rp = require('./module').strRepeat; + console.log(rp('foo', 10)); + }); +} diff --git a/examples/plugin/src/ts/module.ts b/examples/plugin/src/ts/module.ts new file mode 100644 index 000000000..772338786 --- /dev/null +++ b/examples/plugin/src/ts/module.ts @@ -0,0 +1,3 @@ +export function strRepeat(item: string, times: number): string { + return item.repeat(times); +} diff --git a/examples/plugin/tsconfig.json b/examples/plugin/tsconfig.json new file mode 100644 index 000000000..83581c242 --- /dev/null +++ b/examples/plugin/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "esnext", + "moduleResolution": "node", + "lib": ["esnext", "dom", "dom.iterable"], + "allowJs": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "preserve", + "noEmit": true, + "skipLibCheck": true, + "strict": true + }, + "include": ["src/ts"] +} diff --git a/examples/plugin/wpackio.project.js b/examples/plugin/wpackio.project.js index 43f897e61..733aacf73 100644 --- a/examples/plugin/wpackio.project.js +++ b/examples/plugin/wpackio.project.js @@ -42,6 +42,12 @@ module.exports = { main: ['./src/reactapp/index.jsx'], }, }, + { + name: 'tsapp', + entry: { + main: ['./src/ts/main.ts'], + }, + }, ], // Output path relative to the context directory // We need relative path here, else, we can not map to publicPath diff --git a/packages/scripts/__tests__/config/WebpackConfigHelper.spec.ts b/packages/scripts/__tests__/config/WebpackConfigHelper.spec.ts index b0b963a49..8fc56014a 100644 --- a/packages/scripts/__tests__/config/WebpackConfigHelper.spec.ts +++ b/packages/scripts/__tests__/config/WebpackConfigHelper.spec.ts @@ -1,5 +1,7 @@ import { PresetOptions } from '@wpackio/babel-preset-base/lib/preset'; +import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; import miniCssExtractPlugin from 'mini-css-extract-plugin'; +import path from 'path'; import webpack from 'webpack'; import { webpackOptionsOverrideFunction } from '../../src/config/project.config.default'; import { WebpackConfigHelper } from '../../src/config/WebpackConfigHelper'; @@ -130,6 +132,22 @@ describe('CreateWebPackConfig', () => { const plugins = cwc.getPlugins(); expect(plugins).toMatchSnapshot(); }); + test('has fork ts checker when tsconfig.json is present', () => { + const cwc = new WebpackConfigHelper( + projectConfig.files[0], + getConfigFromProjectAndServer(projectConfig, serverConfig), + path.resolve(__dirname, '../../'), // it's a hack cause the project has tsconfig.json + true + ); + const plugins = cwc.getPlugins(); + let hasTsChecker = false; + plugins.forEach(plug => { + if (plug instanceof ForkTsCheckerWebpackPlugin) { + hasTsChecker = true; + } + }); + expect(hasTsChecker).toBeTruthy(); + }); }); // getModule() diff --git a/packages/scripts/package.json b/packages/scripts/package.json index ed8cab131..582a10438 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -53,6 +53,7 @@ "figures": "^2.0.0", "file-loader": "^2.0.0", "find-up": "^3.0.0", + "fork-ts-checker-webpack-plugin": "^0.4.10", "gradient-string": "^1.2.0", "handlebars": "^4.0.12", "inquirer": "^6.2.0", diff --git a/packages/scripts/src/config/WebpackConfigHelper.ts b/packages/scripts/src/config/WebpackConfigHelper.ts index cc5d1fb31..413dac419 100644 --- a/packages/scripts/src/config/WebpackConfigHelper.ts +++ b/packages/scripts/src/config/WebpackConfigHelper.ts @@ -3,6 +3,8 @@ import { PresetOptions, } from '@wpackio/babel-preset-base/lib/preset'; import cleanWebpackPlugin from 'clean-webpack-plugin'; +import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; +import fs from 'fs'; import miniCssExtractPlugin from 'mini-css-extract-plugin'; import path from 'path'; import WatchMissingNodeModulesPlugin from 'react-dev-utils/WatchMissingNodeModulesPlugin'; @@ -260,6 +262,21 @@ export class WebpackConfigHelper { entrypointsKey: 'wpackioEp', }), ]; + // Add ts checker plugin if project has tsconfig.json + const tsconfigPath = path.resolve(this.cwd, './tsconfig.json'); + if (this.fileExists(tsconfigPath)) { + const tsConfig: { tsconfig: string; tslint?: string | boolean } = { + tsconfig: tsconfigPath, + }; + plugins.push( + new ForkTsCheckerWebpackPlugin({ + tsconfig: tsconfigPath, + tslint: undefined, + async: false, + silent: true, + }) + ); + } // Add development specific plugins if (this.isDev) { // Hot Module Replacement @@ -558,4 +575,15 @@ ${bannerConfig.copyrightText}${bannerConfig.credit ? creditNote : ''}`, // Otherwise just return default return defaults; } + + /** + * Check if file exists or not using fs API. + */ + private fileExists(filepath: string): boolean { + try { + return fs.statSync(filepath).isFile(); + } catch (_) { + return false; + } + } } diff --git a/site/src/pages/index.js b/site/src/pages/index.js index 0a95d7947..37b8e0566 100644 --- a/site/src/pages/index.js +++ b/site/src/pages/index.js @@ -39,7 +39,11 @@ const IndexPage = ({ data: { mission } }) => ( # initiate the tooling to your existing project

- npx @wpackio/scripts bootstrap + npx @wpackio/cli +

+

# bootstrap project

+

+ npm run bootstrap

# start development server

diff --git a/yarn.lock b/yarn.lock index ceaee1f7f..46b627f64 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1473,6 +1473,10 @@ "@types/memory-fs" "*" "@types/webpack" "*" +"@types/webpack-env@^1.13.6": + version "1.13.6" + resolved "http://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.13.6.tgz#128d1685a7c34d31ed17010fc87d6a12c1de6976" + "@types/webpack-hot-middleware@^2.16.4": version "2.16.4" resolved "https://registry.yarnpkg.com/@types/webpack-hot-middleware/-/webpack-hot-middleware-2.16.4.tgz#258ecf2ae0ee80a988cc65547b24608fe10be440" @@ -2720,7 +2724,7 @@ chokidar@1.7.0: optionalDependencies: fsevents "^1.0.0" -chokidar@^2.0.2, chokidar@^2.0.3: +chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" dependencies: @@ -4573,6 +4577,21 @@ forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" +fork-ts-checker-webpack-plugin@^0.4.10: + version "0.4.10" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-0.4.10.tgz#e96f87ea599af4501c1a69f44ecfb3163bbf30b9" + dependencies: + babel-code-frame "^6.22.0" + chalk "^2.4.1" + chokidar "^2.0.4" + lodash.endswith "^4.2.1" + lodash.isfunction "^3.0.8" + lodash.isstring "^4.0.1" + lodash.startswith "^4.2.1" + minimatch "^3.0.4" + resolve "^1.5.0" + tapable "^1.0.0" + form-data@~2.3.1, form-data@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" @@ -6405,6 +6424,10 @@ lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" +lodash.endswith@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.endswith/-/lodash.endswith-4.2.1.tgz#fed59ac1738ed3e236edd7064ec456448b37bc09" + lodash.get@^4.0, lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" @@ -6417,6 +6440,14 @@ lodash.isfinite@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz#fb89b65a9a80281833f0b7478b3a5104f898ebb3" +lodash.isfunction@^3.0.8: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051" + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -6429,6 +6460,10 @@ lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" +lodash.startswith@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.startswith/-/lodash.startswith-4.2.1.tgz#c598c4adce188a27e53145731cdc6c0e7177600c" + lodash.tail@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" @@ -9939,6 +9974,10 @@ typescript@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.1.tgz#3362ba9dd1e482ebb2355b02dfe8bcd19a2c7c96" +typescript@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.3.tgz#01b70247a6d3c2467f70c45795ef5ea18ce191d5" + ua-parser-js@0.7.17: version "0.7.17" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac"