Taro 开发小程序, 把 @ 配成 src 路径别名,webpack / tsconfig / scss 三处同步的正确姿势

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__dirnameconfig/ 目录,.. 一层回到项目根,再进 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.scsstab-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 要看清

__dirnameconfig/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/componentsapp/components,所有文件挪得干干净净,还挺有成就感。

然后他来问我:「学长,编译报一堆 @/ 找不到,是怎么回事?」

我一看:config/index.ts 里那个 path.resolve(__dirname, '..', 'src')'src' 是个硬编码字符串,目录改名它不会自动跟tsconfig.jsonpaths'./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
相关推荐
灵枢时代2 小时前
小程序在生鲜配送行业,如何设计夜间预约和次日达的订单处理流程?
数据结构·人工智能·小程序
2601_953720821 天前
【计算机毕业设计】基于微信小程序的拼车服务系统设计与实现
微信小程序·小程序·课程设计
乐启国际旅行社有限公司1 天前
文旅小程序性能优化:分包加载+地图视口懒加载解决景区卡顿与包超限
性能优化·小程序
FungLeo1 天前
Taro 4 微信小程序:RootPortal CSS 变量继承问题与自建 PagePortal 解决方案
微信小程序·taro·css 变量
万岳科技系统开发2 天前
校园跑腿外卖搭建助力高校周边商家拓展线上业务
大数据·人工智能·小程序
微三云 - 廖会灵 (私域系统开发)2 天前
消费返物业费平台搭建:美家时代商业模式拆解与系统开发选型指南
小程序·系统架构
greenbbLV2 天前
中小公司积分商城选型:SaaS与私有化方案对比解析
大数据·前端·小程序
leslie1182 天前
webpack笔记
前端·webpack
2501_915909063 天前
iOS 应用反调试技详解术 检测调试器的原理与防护实践
android·ios·小程序·https·uni-app·iphone·webview