如何让 ts-transformer-keys 与 Vue 一起工作



edit:

现在我觉得自己像个白痴...从昨天晚上开始,我一直在做这件事。今天我意识到我可以测试将转译解析为假:

chainWebpack: config => {
const getCustomTransformers = program => ({
before: [keysTransformer(program)]
});
const transpileOnly = false;
["ts", "tsx"].forEach(rule => {
config.module
.rule(rule)
.use("ts-loader")
.loader("ts-loader")
.tap(options => Object.assign(options, { getCustomTransformers, transpileOnly }));
});
},

而且..这确实有效。我在控制台中看到我的界面键。我现在唯一的问题是 - 我这样做破坏了什么?如果我这样做不安全,有没有其他更好的方法可以做到这一点?

原文:

此时此刻,我的怀疑(从最后一段开始(是ts-loadertranspileOnly: true,选项与变压器不兼容......如果是这样,有什么可做的吗?只是确认或否认我的想法会非常棒。有问题的变压器是今村健二的 ts 变压器键

我认为你需要熟悉 webpack 和打字稿,才能让它工作。如果你像我一样,专业地使用它但不涉及核心功能,你可能会喜欢这个关于转换器的入门:如何编写TypeScript转换插件

在wepack方面,我非常有能力,所以我希望能做到这一点。但是,我是第一次使用 vue 3,而 webpack 是..不同。您可以使用 vue.config.js 来设置一个块,以使用 webpack-merge 或 webpack-chain 修改 webpack 配置。由于我想改变 ts 加载器(我假设(,我使用了链条..我做了一些其他的配置更改,所以我的 vue.config.ts 看起来像这样:

const PackageVars = require('./package-vars.webpack-plugin.js')
const keysTransformer = require('ts-transformer-keys/transformer').default
module.exports = {
configureWebpack: {
plugins: [PackageVars]
},
chainWebpack: config => {
const getCustomTransformers = program => ({
before: [keysTransformer(program)]
})
;['ts', 'tsx'].forEach(rule => {
config.module
.rule(rule)
.use('ts-loader')
.loader('ts-loader')
.tap(options => Object.assign(options, { getCustomTransformers }))
})
},
pluginOptions: {
i18n: {
locale: 'en',
fallbackLocale: 'en',
localeDir: 'locales',
enableInSFC: true
}
},
css: {
loaderOptions: {
sass: {
prependData: `@import "@/styles/global.scss";`
}
}
}
}

这生成了一个 webpack.config.js(正如 Vue Inspect 所报告的那样,这是缩写的,主要是删除与 CSS 相关的编译,因为 stackOverflow 中的字符限制(:

{
mode: 'development',
context: '/Users/me/Public/project',
node: {
setImmediate: false,
process: 'mock',
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
},
//...
resolveLoader: {
modules: [
'/Users/me/Public/project/node_modules/@vue/cli-plugin-typescript/node_modules',
'/Users/me/Public/project/node_modules/@vue/cli-plugin-babel/node_modules',
'node_modules',
'/Users/me/Public/project/node_modules',
'/Users/me/Public/project/node_modules/@vue/cli-service/node_modules'
]
},
module: {
noParse: /^(vue|vue-router|vuex|vuex-router-sync)$/,
rules: [
/* config.module.rule('vue') */
{
test: /.vue$/,
use: [
{
loader: '/Users/me/Public/project/node_modules/cache-loader/dist/cjs.js',
options: {
cacheDirectory: '/Users/me/Public/project/node_modules/.cache/vue-loader',
cacheIdentifier: '1fc0539f'
}
},
{
loader: '/Users/me/Public/project/node_modules/vue-loader/lib/index.js',
options: {
compilerOptions: {
whitespace: 'condense'
},
cacheDirectory: '/Users/me/Public/project/node_modules/.cache/vue-loader',
cacheIdentifier: '1fc0539f'
}
}
]
},
//...
/* config.module.rule('js') */
{
test: /.m?jsx?$/,
exclude: [
function () { /* omitted long function */ }
],
use: [
{
loader: '/Users/me/Public/project/node_modules/cache-loader/dist/cjs.js',
options: {
cacheDirectory: '/Users/me/Public/project/node_modules/.cache/babel-loader',
cacheIdentifier: '0fff5c38'
}
},
{
loader: '/Users/me/Public/project/node_modules/babel-loader/lib/index.js'
}
]
},
/* config.module.rule('eslint') */
{
enforce: 'pre',
test: /.(vue|(j|t)sx?)$/,
exclude: [
/node_modules/,
'/Users/me/Public/project/node_modules/@vue/cli-service/lib'
],
use: [
{
loader: '/Users/me/Public/project/node_modules/eslint-loader/index.js',
options: {
extensions: [
'.js',
'.jsx',
'.vue',
'.ts',
'.tsx'
],
cache: true,
cacheIdentifier: '5749dfb1',
emitWarning: false,
emitError: false,
eslintPath: '/Users/me/Public/project/node_modules/eslint',
formatter: function () { /* omitted long function */ }
}
}
]
},
/* config.module.rule('ts') */
{
test: /.ts$/,
use: [
{
loader: '/Users/me/Public/project/node_modules/cache-loader/dist/cjs.js',
options: {
cacheDirectory: '/Users/me/Public/project/node_modules/.cache/ts-loader',
cacheIdentifier: 'b1785fd2'
}
},
{
loader: '/Users/me/Public/project/node_modules/babel-loader/lib/index.js'
},
{
loader: 'ts-loader',
options: {
transpileOnly: true,
appendTsSuffixTo: [
'\.vue$'
],
happyPackMode: false,
getCustomTransformers: program => ({
before: [keysTransformer(program)]
})
}
}
]
},
/* config.module.rule('tsx') */
{
test: /.tsx$/,
use: [
{
loader: '/Users/me/Public/project/node_modules/cache-loader/dist/cjs.js',
options: {
cacheDirectory: '/Users/me/Public/project/node_modules/.cache/ts-loader',
cacheIdentifier: 'b1785fd2'
}
},
{
loader: '/Users/me/Public/project/node_modules/babel-loader/lib/index.js'
},
{
loader: 'ts-loader',
options: {
transpileOnly: true,
happyPackMode: false,
appendTsxSuffixTo: [
'\.vue$'
],
getCustomTransformers: program => ({
before: [keysTransformer(program)]
})
}
}
]
},
/* config.module.rule('i18n') */
{
resourceQuery: /blockType=i18n/,
type: 'javascript/auto',
use: [
{
loader: '@kazupon/vue-i18n-loader'
}
]
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
name: 'chunk-vendors',
test: /[\/]node_modules[\/]/,
priority: -10,
chunks: 'initial'
},
common: {
name: 'chunk-common',
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
},
minimizer: [
{
options: {
test: /.m?js(?.*)?$/i,
chunkFilter: () => true,
warningsFilter: () => true,
extractComments: false,
sourceMap: true,
cache: true,
cacheKeys: defaultCacheKeys => defaultCacheKeys,
parallel: true,
include: undefined,
exclude: undefined,
minify: undefined,
terserOptions: {
compress: {
arrows: false,
collapse_vars: false,
comparisons: false,
computed_props: false,
hoist_funs: false,
hoist_props: false,
hoist_vars: false,
inline: false,
loops: false,
negate_iife: false,
properties: false,
reduce_funcs: false,
reduce_vars: false,
switches: false,
toplevel: false,
typeofs: false,
booleans: true,
if_return: true,
sequences: true,
unused: true,
conditionals: true,
dead_code: true,
evaluate: true
},
mangle: {
safari10: true
}
}
}
}
]
},
plugins: [
/* config.plugin('vue-loader') */
new VueLoaderPlugin(),
/* config.plugin('define') */
new DefinePlugin(
{
'process.env': {
NODE_ENV: '"development"',
VUE_APP_I18N_LOCALE: '"en"',
VUE_APP_I18N_FALLBACK_LOCALE: '"en"',
BASE_URL: '"/"'
}
}
),
/* config.plugin('case-sensitive-paths') */
new CaseSensitivePathsPlugin(),
/* config.plugin('friendly-errors') */
new FriendlyErrorsWebpackPlugin(
{
additionalTransformers: [
function () { /* omitted long function */ }
],
additionalFormatters: [
function () { /* omitted long function */ }
]
}
),
/* config.plugin('html') */
new HtmlWebpackPlugin(
{
templateParameters: function () { /* omitted long function */ },
template: '/Users/me/Public/project/public/index.html'
}
),
/* config.plugin('pwa') */
new HtmlPwaPlugin(
{
name: 'project'
}
),
/* config.plugin('preload') */
new PreloadPlugin(
{
rel: 'preload',
include: 'initial',
fileBlacklist: [
/.map$/,
/hot-update.js$/
]
}
),
/* config.plugin('prefetch') */
new PreloadPlugin(
{
rel: 'prefetch',
include: 'asyncChunks'
}
),
/* config.plugin('copy') */
new CopyPlugin(
[
{
from: '/Users/me/Public/project/public',
to: '/Users/me/Public/project/dist',
toType: 'dir',
ignore: [
'.DS_Store',
{
glob: 'index.html',
matchBase: false
}
]
}
]
),
/* config.plugin('fork-ts-checker') */
new ForkTsCheckerWebpackPlugin(
{
vue: true,
tslint: false,
formatter: 'codeframe',
checkSyntacticErrors: false
}
),
{
definitions: {
'process.env': {
PACKAGE_VERSION: '"2.0.0"',
PACKAGE_NAME: '"project"'
}
}
}
],
entry: {
app: [
'./src/main.ts'
]
}
}

在我的代码中,我将自述文件中的演示附加到我要使用的接口中(这是在 .ts 文件中,而不是 .vue 文件中,所以我真的半期望它能工作(:

import { keys } from "ts-transformer-keys";
export interface FirebaseUser {
uid: string;
displayName?: string;
email?: string;
phoneNumber?: string;
emailVerified: boolean;
isAnonymous?: boolean;
}
const keysOfProps = keys<FirebaseUser>();
console.log({ keysOfProps });

这应该简化/减少工厂方法的债务,如下所示:

export function factoryFirebaseUser(
data = <Partial<FirebaseUser>>{}
): FirebaseUser {
if (!data.hasOwnProperty("uid")) {
data.uid = undefined;
}
//...
return data as FirebaseUser;
}

但是当我运行npm run serve时,我得到:Uncaught ReferenceError: keys is not defined..你能帮我找到还需要添加它的地方吗?

我想知道加载器配置中所需的transpileOnly: true,选项是否是罪魁祸首?我相信这是为了允许单独配置 babel。

所以是的,添加转译:true确实有效。我打开了一个错误报告,询问有关这是否安全的详细信息,并在官方的不和谐服务器上进行了追查:tl-dr 没有一个活跃的人知道。但至少它有效。

最新更新