Taro 开发小程序, 把 @ 配成 src 路径别名,webpack / tsconfig / scss 三处同步的正确姿势
摘要 :本文讲透 Taro 小程序里
@路径别名的正确配置姿势------webpack alias / tsconfig paths / scss@use三处必须同步 。webpack alias 是真正让@/编译生效的那一处,tsconfig paths 只服务 TS 类型检查和编辑器跳转,scss 的@use '@/...'同样依赖 webpack alias。文章还梳理了 scss@use省略扩展名、共享文件不带_前缀等高频坑点,并给出六条工程惯例,帮你把路径相关的工程问题减少 80%。
各位看官,我敢说,前端工程里被低估的配置,@ 路径别名排进前三没毛病。
一个项目写到二十几个页面、组件一嵌套就四层深,你就懂了------../../../components/Button 这种 ../ 链一长,改一次目录结构,鬼知道哪些文件会先崩。而且 TS 编辑器跳转还老给你指错地方,蠢得让人想骂街。
所以 @ 别名是个基本盘。但------真把这件事做对的人不多 。我见过太多团队配了 tsconfig 就以为完事了,结果 taro build 一跑,Module not found: @/components/Button;或者反过来,配了 webpack 但 TS 类型检查一堆红波浪线。
今天我就把这事讲透:webpack alias / tsconfig paths / scss @use 三处必须同步。任何一处缺位,运行时给你颜色看。

本文要点
@别名把../../../components/Button这种相对路径地狱,变成@/components/Button的绝对引用- webpack alias 是真正让
@/编译生效的那一处------打包时不读 tsconfig - tsconfig
paths只服务 TS 类型检查和编辑器跳转,不是打包路径 - scss 的
@use '@/...'也走 webpack alias,所以是第三处同步 - scss 里
@use的路径省略.scss扩展名 ,且共享文件命名不要加_前缀(项目里这样约定,省事) - 三处缺任一处的症状表(图2)
一、不配 @ 的代价,你品一品
先看图,感受一下什么叫「相对路径地狱」。

左边那一串 ../../../../components/Button,看着就让人血压上升。改目录结构的时候,你自己数数得改多少处------而且关键是,这些 ../ 全是相对当前位置的,文件挪一层就得全部重写。
右边 @/components/Button,不管你文件在三层、五层、八层嵌套,永远指向同一个 src/components/Button。重构?随便挪,@/ 永远不骗你。
这事儿我刚入行那会儿也犯过:一个项目没配别名,写到三十几个组件,某天重构目录结构,一下午都在数 ../。从那以后,新项目 @/ 别名我第一件事就配。
二、webpack alias:真正让 @/ 编译生效的那一处
Taro 项目里,配置在 config/index.ts:
ts
// config/index.ts
import { defineConfig } from '@tarojs/cli'
import path from 'path'
export default defineConfig(async (ctx, env) => ({
// ... 其它配置
alias: {
'@': path.resolve(__dirname, '..', 'src')
},
// ...
}))
一行 path.resolve(__dirname, '..', 'src') 把 @ 钉死在 src/ 根目录。这是打包时唯一真正让 @/components/Button 解析到 src/components/Button/index.tsx 的那一步。
注意 path.resolve 的 __dirname 是 config/ 目录,.. 一层回到项目根,再进 src。这个相对偏移在不同项目里不一样,你得对着自己的项目目录看------别瞎抄。
三、tsconfig paths:只服务 TS 类型检查和编辑器跳转
json
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
// ... 其它
}
}
看起来很简单对吧?但这是踩坑最多的地方。
核心认知:tsconfig 的 paths 字段,TS 编译器和编辑器会读,webpack 打包器不读。
什么意思?意思是:
- 你配了 tsconfig paths,VSCode 里
@/components/Button能跳转、TS 类型检查能过 - 但你跑
taro build,webpack 看 tsconfig.json 一眼都不看,它只认自己的resolve.alias - 结果:编辑器一片祥和,打包
Module not found: Can't resolve '@/components/Button'
我第一次碰到这问题的时候懵了好久------明明 TS 不报错啊?后来翻 webpack 文档才知道,两者是完全独立的解析链 。这是很多人对 @ 别名的第一个核心误解。
所以别只配 tsconfig 就以为完事了,webpack alias 必须单独配。
四、scss 里的 @use '@/...':第三处同步
Taro 项目里,样式文件用 SCSS Modules 是常态。共享样式(比如设计 token、通用布局)放 src/styles/ 下:
text
src/
styles/
tokens.scss # 设计 token(颜色、间距、字号变量)
tab-page.scss # 通用 tab 页骨架
app.scss # 全局入口
pages/
messages/
index.scss
index.tsx
页面 scss 里 @use 共享样式:
scss
// src/pages/messages/index.scss
@use '@/styles/tab-page.scss';
// 或共享 token
@use '@/styles/tokens';
注意几个坑点------这是 sass 的特性,配错会直接报错:
坑 1:@use 路径省略 .scss 扩展名
scss
// ❌ 错误:带扩展名反而报错
@use '@/styles/tokens.scss';
// ✓ 正确:省略扩展名
@use '@/styles/tokens';
dart-sass 的 @use 规则是不要带扩展名 。手贱带上 tokens.scss,直接 Can't find stylesheet to import.,看到这行错先看看是不是这里。

坑 2:共享文件命名别加 _ 前缀
sass 的「partial」惯例是 _tokens.scss,但在 Taro 的 sass-loader 配置下,项目里约定共享样式直接命名 tokens.scss、tab-page.scss (无下划线)。这样 @use '@/styles/tokens' 一对一映射,简洁。
如果你非要用 partial,得这样写:
scss
// 文件命名 _tokens.scss
// @use 写法
@use '@/styles/tokens'; // sass 会自动找 _tokens.scss
也就是说 _ 前缀 sass 会自动补,但项目里约定不带下划线 ------避免团队里有人 @use '@/styles/_tokens'、有人 @use '@/styles/tokens',混着写。统一不带,最省心。
坑 3:scss 的 @use 也走 webpack alias
@use '@/styles/tokens' 这个 @/,最后还是 webpack 在解析------sass-loader 拿到路径丢给 webpack 的 resolve.alias。所以如果 webpack alias 没配,scss 这步就直接报路径解析失败。
这就是为什么我强调「三处同步」------scss 的 @use 依赖 webpack alias,是第三处同步,不是独立的第四处。
五、为什么三处必须同步(核心认知)
把上面的逻辑串起来画一张图:

下面是三处配置的依赖关系图:
#mermaid-svg-SZFln8VuqLpTCS3K{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-SZFln8VuqLpTCS3K .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-SZFln8VuqLpTCS3K .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-SZFln8VuqLpTCS3K .error-icon{fill:#552222;}#mermaid-svg-SZFln8VuqLpTCS3K .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SZFln8VuqLpTCS3K .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-SZFln8VuqLpTCS3K .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SZFln8VuqLpTCS3K .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SZFln8VuqLpTCS3K .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-SZFln8VuqLpTCS3K .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SZFln8VuqLpTCS3K .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SZFln8VuqLpTCS3K .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SZFln8VuqLpTCS3K .marker.cross{stroke:#333333;}#mermaid-svg-SZFln8VuqLpTCS3K svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SZFln8VuqLpTCS3K p{margin:0;}#mermaid-svg-SZFln8VuqLpTCS3K .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-SZFln8VuqLpTCS3K .cluster-label text{fill:#333;}#mermaid-svg-SZFln8VuqLpTCS3K .cluster-label span{color:#333;}#mermaid-svg-SZFln8VuqLpTCS3K .cluster-label span p{background-color:transparent;}#mermaid-svg-SZFln8VuqLpTCS3K .label text,#mermaid-svg-SZFln8VuqLpTCS3K span{fill:#333;color:#333;}#mermaid-svg-SZFln8VuqLpTCS3K .node rect,#mermaid-svg-SZFln8VuqLpTCS3K .node circle,#mermaid-svg-SZFln8VuqLpTCS3K .node ellipse,#mermaid-svg-SZFln8VuqLpTCS3K .node polygon,#mermaid-svg-SZFln8VuqLpTCS3K .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SZFln8VuqLpTCS3K .rough-node .label text,#mermaid-svg-SZFln8VuqLpTCS3K .node .label text,#mermaid-svg-SZFln8VuqLpTCS3K .image-shape .label,#mermaid-svg-SZFln8VuqLpTCS3K .icon-shape .label{text-anchor:middle;}#mermaid-svg-SZFln8VuqLpTCS3K .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-SZFln8VuqLpTCS3K .rough-node .label,#mermaid-svg-SZFln8VuqLpTCS3K .node .label,#mermaid-svg-SZFln8VuqLpTCS3K .image-shape .label,#mermaid-svg-SZFln8VuqLpTCS3K .icon-shape .label{text-align:center;}#mermaid-svg-SZFln8VuqLpTCS3K .node.clickable{cursor:pointer;}#mermaid-svg-SZFln8VuqLpTCS3K .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-SZFln8VuqLpTCS3K .arrowheadPath{fill:#333333;}#mermaid-svg-SZFln8VuqLpTCS3K .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-SZFln8VuqLpTCS3K .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-SZFln8VuqLpTCS3K .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SZFln8VuqLpTCS3K .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-SZFln8VuqLpTCS3K .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SZFln8VuqLpTCS3K .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-SZFln8VuqLpTCS3K .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-SZFln8VuqLpTCS3K .cluster text{fill:#333;}#mermaid-svg-SZFln8VuqLpTCS3K .cluster span{color:#333;}#mermaid-svg-SZFln8VuqLpTCS3K div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-SZFln8VuqLpTCS3K .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-SZFln8VuqLpTCS3K rect.text{fill:none;stroke-width:0;}#mermaid-svg-SZFln8VuqLpTCS3K .icon-shape,#mermaid-svg-SZFln8VuqLpTCS3K .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SZFln8VuqLpTCS3K .icon-shape p,#mermaid-svg-SZFln8VuqLpTCS3K .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-SZFln8VuqLpTCS3K .icon-shape .label rect,#mermaid-svg-SZFln8VuqLpTCS3K .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SZFln8VuqLpTCS3K .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-SZFln8VuqLpTCS3K .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-SZFln8VuqLpTCS3K :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} @/ 路径别名
webpack alias
tsconfig paths
scss @use
打包编译生效
taro build 解析 @/
TS 类型检查
编辑器跳转
样式解析
sass-loader 走 alias
src/ 根目录
@ 这个符号,最终必须被同一根绳子拴住 ------src/ 根目录。三处配置,是从三个不同角度(打包、类型检查、scss 解析)指向同一根。
任何一处缺位,对应的环节就断链:
| 缺哪处 | 现象 | 在哪一步挂 |
|---|---|---|
| 只配 webpack alias | 编辑器跳转错、TS 类型检查报红波浪线 | VSCode / tsc --noEmit |
| 只配 tsconfig paths | 编辑器一片祥和,打包 Module not found |
taro build |
| webpack alias 漏配 scss 支持 | scss @use '@/...' 报解析失败 |
taro build |
| 全部漏配 | 三处全报错,三选一的裂开 | 全程 |
这就是我说的「三处一处都不能少」。单独看每处都很简单,合起来就是个系统性配置。
我刚开始搞 Taro 项目那会儿,就是栽在「只配 tsconfig」这个坑里------各位看官知道这种坑最恶心的地方在哪吗?不是错得明显让你好定位,而是编辑器一片祥和、打包一跑满屏红 。我当时还以为是 webpack 有 bug,翻了半天文档也没翻到点上。后来拍脑袋想:TS 不报错、VSCode 跳转正常,凭什么 webpack 就不认?这一拍就想通了------tsconfig paths 跟 webpack alias 是两套独立的解析链,TS 不等于打包。
从那以后,我每次新建项目都把这条铁律写进工程模板 README:webpack alias 与 tsconfig paths 必须成对配,一处都不能省。哪怕赶进度省时间,这一对也必同步------省下的两分钟后面调试要还几小时,不划算。
六、常见翻车现场清单
这些年带团队 + 自己踩坑,我把高频翻车点归了一下:
1. 静态资源引入用 import,别用 require
ts
// ✓ 正确:让 webpack 走 alias 解析
import Logo from '@/assets/icons/logo.png'
// ✗ 错误:require 不会走 alias
const Logo = require('../../../assets/icons/logo.png')
import 走 webpack 编译,alias 生效;require 在某些配置下会被原样输出,alias 不生效。
2. 共享 scss 文件命名不带 _
前面讲过了,再强调一次------团队约定 tokens.scss 不是 _tokens.scss,@use '@/styles/tokens' 干净映射。
3. 静态目录调整后 alias 路径要跟着改
ts
// 如果 src 目录改名了(比如改成 app/)
alias: {
'@': path.resolve(__dirname, '..', 'app') // 同步改这里
}
path.resolve(__dirname, '..', 'src') 这个 'src' 是硬编码字符串,目录重命名时这个字符串不会自动跟着改 。我见过团队把 src 改成 app/ 之后,忘了改 alias,全项目 @/ 全废。
4. 存量 ../ 路径不要混着写
新代码一律 @/xxx,绝不使用 ../ (除非是当前目录的 ./)。存量老代码里的 ../ 是历史遗留,别学 ,也别新写。@/ 是硬规则,比 ../ 安全得多------../ 是相对当前位置的,换个目录就崩。
5. path.resolve 的 __dirname 要看清
__dirname 在 config/index.ts 里是 config/ 目录(注意 Taro 3/4 项目结构可能不同):
text
project-root/
config/
index.ts ← __dirname 在这里
src/
所以 path.resolve(__dirname, '..', 'src') 是 config/.. → 项目根,再进 src。如果是 config/index.ts 在别的位置(比如有的项目在根目录),偏移就不同------别无脑抄别人的配置,对着自己的目录看。
6. 一个真实的翻车案例(顺便当个反面教材)
去年带团队那会儿,有个新同事接手维护模块,觉得 src/ 这个名字太通用(确实通用),于是脑门一热把整个 src 目录重命名成了 app/------src/components → app/components,所有文件挪得干干净净,还挺有成就感。
然后他来问我:「学长,编译报一堆 @/ 找不到,是怎么回事?」
我一看:config/index.ts 里那个 path.resolve(__dirname, '..', 'src'),'src' 是个硬编码字符串,目录改名它不会自动跟 。tsconfig.json 的 paths 里 './src/*' 也是死的。
改两处字符串的事,他花了俩小时没定位到,因为 git diff 一看全是文件挪动的修改,配置里那两行小字根本没人会注意。
各位看官,目录改名是个高危操作 。要改,先全局搜 path.resolve.*src、'./src/*'、@/ 别名相关配置,把所有引用点列出来再动手。改完了还要顺手过一遍打包产物确认没漏。这是工程里少有的「动作小、爆炸半径大」的事故源。
七、我的工程惯例
最后给团队立个规矩,贴墙上------这六条都是这些年从血泪史里提炼的,今天一并交给各位:
1. webpack alias 配 @ → src 根(一行不能少)
2. tsconfig paths 配 @/* → ./src/*(和 webpack alias 同步)
3. scss @use 用 @/ 路径,省略扩展名,文件不带 _ 前缀
4. 静态资源 import from '@/...',不用 require
5. 业务代码一律 @/,绝不写 ../(./ 同目录除外)
6. 存量 ../ 历史遗留可以容忍,新代码绝不写
六条不多,但守住这六条,路径相关的工程问题能少掉 80%------各位看官记住一句话就行:@/ 这条绳子,三头都得拴在同一根桩上 。webpack alias、tsconfig paths、scss @use,一处缺位,工程就给你颜色看。
配置检查清单(Mermaid 速查)
配完三处,用下面这张图自查一遍,缺哪头一目了然:
#mermaid-svg-O8zQ6jMOCEBvUa4c{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-O8zQ6jMOCEBvUa4c .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-O8zQ6jMOCEBvUa4c .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-O8zQ6jMOCEBvUa4c .error-icon{fill:#552222;}#mermaid-svg-O8zQ6jMOCEBvUa4c .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-O8zQ6jMOCEBvUa4c .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-O8zQ6jMOCEBvUa4c .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-O8zQ6jMOCEBvUa4c .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-O8zQ6jMOCEBvUa4c .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-O8zQ6jMOCEBvUa4c .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-O8zQ6jMOCEBvUa4c .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-O8zQ6jMOCEBvUa4c .marker{fill:#333333;stroke:#333333;}#mermaid-svg-O8zQ6jMOCEBvUa4c .marker.cross{stroke:#333333;}#mermaid-svg-O8zQ6jMOCEBvUa4c svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-O8zQ6jMOCEBvUa4c p{margin:0;}#mermaid-svg-O8zQ6jMOCEBvUa4c .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-O8zQ6jMOCEBvUa4c .cluster-label text{fill:#333;}#mermaid-svg-O8zQ6jMOCEBvUa4c .cluster-label span{color:#333;}#mermaid-svg-O8zQ6jMOCEBvUa4c .cluster-label span p{background-color:transparent;}#mermaid-svg-O8zQ6jMOCEBvUa4c .label text,#mermaid-svg-O8zQ6jMOCEBvUa4c span{fill:#333;color:#333;}#mermaid-svg-O8zQ6jMOCEBvUa4c .node rect,#mermaid-svg-O8zQ6jMOCEBvUa4c .node circle,#mermaid-svg-O8zQ6jMOCEBvUa4c .node ellipse,#mermaid-svg-O8zQ6jMOCEBvUa4c .node polygon,#mermaid-svg-O8zQ6jMOCEBvUa4c .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-O8zQ6jMOCEBvUa4c .rough-node .label text,#mermaid-svg-O8zQ6jMOCEBvUa4c .node .label text,#mermaid-svg-O8zQ6jMOCEBvUa4c .image-shape .label,#mermaid-svg-O8zQ6jMOCEBvUa4c .icon-shape .label{text-anchor:middle;}#mermaid-svg-O8zQ6jMOCEBvUa4c .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-O8zQ6jMOCEBvUa4c .rough-node .label,#mermaid-svg-O8zQ6jMOCEBvUa4c .node .label,#mermaid-svg-O8zQ6jMOCEBvUa4c .image-shape .label,#mermaid-svg-O8zQ6jMOCEBvUa4c .icon-shape .label{text-align:center;}#mermaid-svg-O8zQ6jMOCEBvUa4c .node.clickable{cursor:pointer;}#mermaid-svg-O8zQ6jMOCEBvUa4c .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-O8zQ6jMOCEBvUa4c .arrowheadPath{fill:#333333;}#mermaid-svg-O8zQ6jMOCEBvUa4c .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-O8zQ6jMOCEBvUa4c .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-O8zQ6jMOCEBvUa4c .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-O8zQ6jMOCEBvUa4c .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-O8zQ6jMOCEBvUa4c .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-O8zQ6jMOCEBvUa4c .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-O8zQ6jMOCEBvUa4c .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-O8zQ6jMOCEBvUa4c .cluster text{fill:#333;}#mermaid-svg-O8zQ6jMOCEBvUa4c .cluster span{color:#333;}#mermaid-svg-O8zQ6jMOCEBvUa4c div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-O8zQ6jMOCEBvUa4c .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-O8zQ6jMOCEBvUa4c rect.text{fill:none;stroke-width:0;}#mermaid-svg-O8zQ6jMOCEBvUa4c .icon-shape,#mermaid-svg-O8zQ6jMOCEBvUa4c .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-O8zQ6jMOCEBvUa4c .icon-shape p,#mermaid-svg-O8zQ6jMOCEBvUa4c .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-O8zQ6jMOCEBvUa4c .icon-shape .label rect,#mermaid-svg-O8zQ6jMOCEBvUa4c .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-O8zQ6jMOCEBvUa4c .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-O8zQ6jMOCEBvUa4c .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-O8zQ6jMOCEBvUa4c :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 检查点
配置三处
webpack alias
config/index.ts
tsconfig paths
tsconfig.json
scss @use
@/styles/tokens
taro build 通过
TS 类型检查无红波浪线
scss 编译无报错
✅ 三处同步完成
小结
@ 别名这件事,看着是配置,实则是工程基本功。
路径相关的 bug,十个里有八个是配错位置、漏配文件、改了一处忘了另一处------本质上都是「把 @/ 当成一个无所不能的符号 」的误解。它不是。@ 是一根绳子,三头分别拴在 webpack alias、tsconfig paths、scss @use 三个桩上,缺哪头哪头就断。你以为你配齐了,其实只是编辑器看着舒服------打包器可不跟你客气。
核心认知就一句话 :tsconfig paths 只服务类型检查和编辑器,打包时 webpack 不读它 。真正让 @/ 在编译期生效的是 webpack alias。scss 的 @use '@/...' 同样依赖 webpack alias,是第三处同步。
各位看官把这三处的依赖关系理清楚,配的时候一处不漏,路径问题就从你的工程里彻底消失了。
希望看官您用发财的小手点个小赞哈,让更多同学看到,少走弯路。要是你有更优雅的组织方式,欢迎在评论区吐槽,我也想再攒点实战素材。
参考链接
推荐阅读
- 本文由 FungLeo 原创,Deepseek 优化校阅
- 阅读我的其他技术博客:blog.csdn.net/fungleo