1 | const path = require('path')
|
2 |
|
3 | module.exports = (api, projectOptions) => {
|
4 | const fs = require('fs')
|
5 | const useThreads = process.env.NODE_ENV === 'production' && !!projectOptions.parallel
|
6 |
|
7 | const { semver, loadModule } = require('@vue/cli-shared-utils')
|
8 | const vue = loadModule('vue', api.service.context)
|
9 | const isVue3 = (vue && semver.major(vue.version) === 3)
|
10 |
|
11 | api.chainWebpack(config => {
|
12 | config.resolveLoader.modules.prepend(path.join(__dirname, 'node_modules'))
|
13 |
|
14 | if (!projectOptions.pages) {
|
15 | config.entry('app')
|
16 | .clear()
|
17 | .add('./src/main.ts')
|
18 | }
|
19 |
|
20 | config.resolve
|
21 | .extensions
|
22 | .prepend('.ts')
|
23 | .prepend('.tsx')
|
24 |
|
25 | const tsRule = config.module.rule('ts').test(/\.ts$/)
|
26 | const tsxRule = config.module.rule('tsx').test(/\.tsx$/)
|
27 |
|
28 |
|
29 | const addLoader = ({ name, loader, options }) => {
|
30 | tsRule.use(name).loader(loader).options(options)
|
31 | tsxRule.use(name).loader(loader).options(options)
|
32 | }
|
33 |
|
34 | addLoader({
|
35 | name: 'cache-loader',
|
36 | loader: require.resolve('cache-loader'),
|
37 | options: api.genCacheConfig('ts-loader', {
|
38 | 'ts-loader': require('ts-loader/package.json').version,
|
39 | 'typescript': require('typescript/package.json').version,
|
40 | modern: !!process.env.VUE_CLI_MODERN_BUILD
|
41 | }, 'tsconfig.json')
|
42 | })
|
43 |
|
44 | if (useThreads) {
|
45 | addLoader({
|
46 | name: 'thread-loader',
|
47 | loader: require.resolve('thread-loader'),
|
48 | options:
|
49 | typeof projectOptions.parallel === 'number'
|
50 | ? { workers: projectOptions.parallel }
|
51 | : {}
|
52 | })
|
53 | }
|
54 |
|
55 | if (api.hasPlugin('babel')) {
|
56 | addLoader({
|
57 |
|
58 |
|
59 |
|
60 | name: 'babel-loader',
|
61 |
|
62 | loader: require.resolve('babel-loader')
|
63 | })
|
64 | }
|
65 | addLoader({
|
66 | name: 'ts-loader',
|
67 | loader: require.resolve('ts-loader'),
|
68 | options: {
|
69 | transpileOnly: true,
|
70 | appendTsSuffixTo: ['\\.vue$'],
|
71 |
|
72 | happyPackMode: useThreads
|
73 | }
|
74 | })
|
75 |
|
76 | tsxRule.use('ts-loader').loader(require.resolve('ts-loader')).tap(options => {
|
77 | options = Object.assign({}, options)
|
78 | delete options.appendTsSuffixTo
|
79 | options.appendTsxSuffixTo = ['\\.vue$']
|
80 | return options
|
81 | })
|
82 |
|
83 |
|
84 |
|
85 | if (!process.env.VUE_CLI_TEST) {
|
86 | if (isVue3) {
|
87 | config
|
88 | .plugin('fork-ts-checker')
|
89 | .use(require('fork-ts-checker-webpack-plugin-v5'), [{
|
90 | typescript: {
|
91 | extensions: {
|
92 | vue: {
|
93 | enabled: true,
|
94 | compiler: '@vue/compiler-sfc'
|
95 | }
|
96 | },
|
97 | diagnosticOptions: {
|
98 | semantic: true,
|
99 |
|
100 | syntactic: useThreads
|
101 | }
|
102 | }
|
103 | }])
|
104 | } else {
|
105 | config
|
106 | .plugin('fork-ts-checker')
|
107 | .use(require('fork-ts-checker-webpack-plugin'), [{
|
108 | vue: { enabled: true, compiler: 'vue-template-compiler' },
|
109 | tslint: projectOptions.lintOnSave !== false && fs.existsSync(api.resolve('tslint.json')),
|
110 | formatter: 'codeframe',
|
111 |
|
112 | checkSyntacticErrors: useThreads
|
113 | }])
|
114 | }
|
115 | }
|
116 | })
|
117 |
|
118 | if (!api.hasPlugin('eslint')) {
|
119 | api.registerCommand('lint', {
|
120 | description: 'lint source files with TSLint',
|
121 | usage: 'vue-cli-service lint [options] [...files]',
|
122 | options: {
|
123 | '--format [formatter]': 'specify formatter (default: codeFrame)',
|
124 | '--no-fix': 'do not fix errors',
|
125 | '--formatters-dir [dir]': 'formatter directory',
|
126 | '--rules-dir [dir]': 'rules directory'
|
127 | }
|
128 | }, args => {
|
129 | return require('./lib/tslint')(args, api)
|
130 | })
|
131 | }
|
132 | }
|