Skip to content

Commit

Permalink
fix: resolve vue.js cache bug and add e2e tests
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-oles committed May 23, 2020
1 parent 8b383df commit 4d6b5fb
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 30 deletions.
108 changes: 108 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* Faster [TypeScript](https://github.com/Microsoft/TypeScript) type checking and [ESLint](https://eslint.org/) linting (each on a separate process) 🏎
* Support for modern TypeScript features like [project references](https://www.typescriptlang.org/docs/handbook/project-references.html) and [incremental mode](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#faster-subsequent-builds-with-the---incremental-flag)
* Support for [Yarn PnP](https://classic.yarnpkg.com/en/docs/pnp/) 🧶
* Support for [Vue Single File Component](https://vuejs.org/v2/guide/single-file-components.html) ✅ 
* Nice errors reporting with the [code frame](https://babeljs.io/docs/en/next/babel-code-frame.html) formatter 🌈

## Installation
Expand Down Expand Up @@ -194,6 +195,10 @@ Options for the issues filtering (`issues` option object).
| `exclude` | `object` or `function` or `array` | `undefined` | Same as `include` but issues that match this predicate will be excluded. |

## Yarn PnP
To enable Yarn PnP support, follow these steps:

<details>
<summary>Expand Yarn PnP set up instruction</summary>

To enable Yarn PnP, you have to install [`ts-pnp`](https://github.com/arcanis/ts-pnp) and [`pnp-webpack-plugin`](https://github.com/arcanis/pnp-webpack-plugin) package:

Expand Down Expand Up @@ -243,6 +248,109 @@ module.exports = {
]
};
```
</details>

## Vue.js
To enable Vue.js support, follow these steps:

<details>
<summary>Expand Vue.js set up instruction</summary>

1. Ensure you have all required packages installed:
```sh
# with npm
npm install --save vue vue-class-component
npm install --save-dev vue-loader ts-loader css-loader vue-template-compiler

# with yarn
yarn add vue vue-class-component
yarn add --dev vue-loader ts-loader css-loader vue-template-compiler
```

2. Add `tsconfig.json` configuration:
```json
{
"compilerOptions": {
"experimentalDecorators": true,
"jsx": "preserve",
"target": "ES5",
"lib": ["ES6", "DOM"],
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"~/*": ["src/*"]
},
"sourceMap": true
},
"include": [
"src/**/*.ts",
"src/**/*.vue"
],
"exclude": [
"node_modules"
]
}
```

3. Add `webpack.config.js` configuration:
```js
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

module.exports = {
entry: './src/index.ts',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.ts$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
appendTsSuffixTo: [/\.vue$/]
}
},
],
},
resolve: {
extensions: ['.ts', '.js', '.vue', '.json'],
alias: {
'@': path.resolve(__dirname, './src'),
'~': path.resolve(__dirname, './src'),
}
},
plugins: [
new VueLoaderPlugin(),
new ForkTsCheckerWebpackPlugin({
typescript: {
extensions: {
vue: true
}
}
})
]
};
```

4. Add `src/types/vue.d.ts` file to shim `.vue` modules:
```typescript
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}
```

5. If you are working in VSCode, you can get the [Vetur](https://marketplace.visualstudio.com/items?itemName=octref.vetur) extension to complete the developer workflow.

</details>

## Type-Only modules watching

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ function createTypeScriptEmbeddedExtension({
return host.watchFile(
embeddedFileName,
(innerFileName: string, eventKind: ts.FileWatcherEventKind) => {
embeddedSourceCache.delete(innerFileName);
embeddedSourceCache.delete(embeddedFileName);
return callback(fileName, eventKind);
},
poolingInterval
Expand Down
118 changes: 89 additions & 29 deletions test/e2e/TypeScriptVueExtension.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,93 @@ describe('TypeScript Vue Extension', () => {
await sandbox.cleanup();
});

it.each([{ async: true, webpack: '^4.0.0', typescript: '2.7.1', tsloader: '^5.0.0' }])(
'reports semantic error for %p',
async ({ async, webpack, typescript, tsloader }) => {
await sandbox.load([
await readFixture(join(__dirname, 'fixtures/environment/typescript-vue.fixture'), {
FORK_TS_CHECKER_WEBPACK_PLUGIN_VERSION: JSON.stringify(
FORK_TS_CHECKER_WEBPACK_PLUGIN_VERSION
),
TS_LOADER_VERSION: JSON.stringify(tsloader),
TYPESCRIPT_VERSION: JSON.stringify(typescript),
WEBPACK_VERSION: JSON.stringify(webpack),
WEBPACK_CLI_VERSION: JSON.stringify(WEBPACK_CLI_VERSION),
WEBPACK_DEV_SERVER_VERSION: JSON.stringify(WEBPACK_DEV_SERVER_VERSION),
ASYNC: JSON.stringify(async),
}),
await readFixture(join(__dirname, 'fixtures/implementation/typescript-vue.fixture')),
]);

const driver = createWebpackDevServerDriver(
sandbox.spawn('npm run webpack-dev-server'),
async
);

// first compilation is successful
await driver.waitForNoErrors();

// TODO: it seems that single-file components are broken on the ts-loader/typescript side
}
);
it.each([
{ async: true, typescript: '2.7.1', tsloader: '^5.0.0' },
{ async: false, typescript: '~3.0.0', tsloader: '^5.0.0' },
{ async: true, typescript: '~3.6.0', tsloader: '^6.0.0' },
{ async: false, typescript: '^3.8.0', tsloader: '^7.0.0' },
])('reports semantic error for %p', async ({ async, typescript, tsloader }) => {
await sandbox.load([
await readFixture(join(__dirname, 'fixtures/environment/typescript-vue.fixture'), {
FORK_TS_CHECKER_WEBPACK_PLUGIN_VERSION: JSON.stringify(
FORK_TS_CHECKER_WEBPACK_PLUGIN_VERSION
),
TS_LOADER_VERSION: JSON.stringify(tsloader),
TYPESCRIPT_VERSION: JSON.stringify(typescript),
WEBPACK_VERSION: JSON.stringify('^4.0.0'),
WEBPACK_CLI_VERSION: JSON.stringify(WEBPACK_CLI_VERSION),
WEBPACK_DEV_SERVER_VERSION: JSON.stringify(WEBPACK_DEV_SERVER_VERSION),
ASYNC: JSON.stringify(async),
}),
await readFixture(join(__dirname, 'fixtures/implementation/typescript-vue.fixture')),
]);

const driver = createWebpackDevServerDriver(sandbox.spawn('npm run webpack-dev-server'), async);
let errors: string[] = [];

// first compilation is successful
await driver.waitForNoErrors();

// let's modify user model file
await sandbox.patch(
'src/component/LoggedIn.vue',
"import User, { getUserName } from '@/model/User';",
"import User from '@/model/User';"
);

// next compilation should have missing function error
errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in src/component/LoggedIn.vue 28:24-35',
"TS2304: Cannot find name 'getUserName'.",
' 26 | ',
' 27 | get userName() {',
" > 28 | return this.user ? getUserName(this.user) : '';",
' | ^^^^^^^^^^^',
' 29 | }',
' 30 | ',
' 31 | async logout() {',
].join('\n'),
]);

// let's fix it
await sandbox.patch(
'src/component/LoggedIn.vue',
"return this.user ? getUserName(this.user) : '';",
"return this.user ? `${this.user.firstName} ${this.user.lastName}` : '';"
);

await driver.waitForNoErrors();

// let's modify user model file again
await sandbox.patch('src/model/User.ts', ' firstName?: string;\n', '');

// not we should have an error about missing firstName property
errors = await driver.waitForErrors();
expect(errors).toEqual([
[
'ERROR in src/component/LoggedIn.vue 28:37-46',
"TS2339: Property 'firstName' does not exist on type 'User'.",
' 26 | ',
' 27 | get userName() {',
" > 28 | return this.user ? `${this.user.firstName} ${this.user.lastName}` : '';",
' | ^^^^^^^^^',
' 29 | }',
' 30 | ',
' 31 | async logout() {',
].join('\n'),
[
'ERROR in src/model/User.ts 11:16-25',
"TS2339: Property 'firstName' does not exist on type 'User'.",
' 9 | ',
' 10 | function getUserName(user: User): string {',
' > 11 | return [user.firstName, user.lastName]',
' | ^^^^^^^^^',
' 12 | .filter(name => name !== undefined)',
" 13 | .join(' ');",
' 14 | }',
].join('\n'),
]);
});
});
6 changes: 6 additions & 0 deletions test/e2e/fixtures/environment/typescript-vue.fixture
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,9 @@ module.exports = {
})
]
};

/// src/vue-shim.d.ts
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}

0 comments on commit 4d6b5fb

Please sign in to comment.