Extract and move
Skill manman1414/frontend-refactor-skills/skills/extract-and-move
React/Vue/TS 前端重构 Agent Skills(行为不变重构、拆文件、绞杀者迁移)
npx -y skills add manman1414/frontend-refactor-skills --skill extract-and-moveAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Extracts and relocates React components, Vue 2/3 SFCs, hooks, composables, stores, and TypeScript modules with stable public APIs and correct import paths. Use when splitting large files, moving shared UI to packages, creating composables/hooks folders, reorganizing feature modules, or fixing circular dependencies in frontend code.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
5.7 KB, as published. Nobody here has run it
Extract and Move (Frontend)
<!-- Author: Administrator | Date: 2026-07-05 -->Move or split code without changing behavior. Focus: file boundaries, import graph, public exports.
<HARD-GATE> Step 1 is always a pure move (git mv or copy with identical content). Logic changes come only after move compiles and tests pass. </HARD-GATE>When to use
- Split 500+ line SFC / component file
- Extract
components/,composables/,hooks/,stores/slice - Move shared code to
packages/uiorsrc/shared - Fix circular imports by introducing a leaf module
- Colocate tests/stories next to moved files
Target layout (adapt to repo)
src/features/orders/
├── index.ts # public barrel — minimal exports
├── components/
│ ├── OrderList.tsx
│ └── OrderRow.tsx
├── composables/ # Vue
│ └── useOrderFilters.ts
├── hooks/ # React
│ └── useOrderFilters.ts
├── types.ts
└── api.ts
Barrel rule: index.ts exports only what other features need. Keep internals private.
Workflow
Step 1 — Map dependencies
Before moving, list:
- [ ] Who imports this file? (grep importers)
- [ ] What does this file import?
- [ ] Any circular path? A → B → A
- [ ] Framework: React | Vue 2 | Vue 3
- [ ] Path alias: @/ @features/ etc.
Step 2 — Define public API
Write the smallest export surface:
| Moved unit | Public export | Keep private |
|---|---|---|
| Component | Default or named export | Internal subcomponents |
| Hook/composable | Named useXxx | Helper functions |
| Types | export type only | — |
| Store (Pinia/Vuex/Zustand) | Store factory or hook | Internal actions |
Step 3 — Pure move
- Create destination file(s) with identical content
- Update imports in moved file (paths only)
- Re-export from old path temporarily OR update all importers in one commit
- Run typecheck — fix path aliases only
npm run typecheck
npm test -- --run
Vue SFC moves: move .vue + scoped style together; check @/ asset paths in <style>.
React moves: update relative imports; if using barrel, update index.ts re-exports.
Step 4 — Break cycles (if needed)
Preferred order:
- Extract shared types to
types.ts(no runtime imports) - Extract pure utils (no component imports)
- Inject dependencies via props/hooks instead of cross-feature imports
❌ features/a → features/b → features/a
✅ features/a → shared/types
features/b → shared/types
Step 5 — Clean up
- Remove dead re-exports from old paths
- Add deprecation comment if old path kept temporarily:
/** @deprecated Import from '@/features/orders' */
export { OrderList } from "./features/orders";
- Update Storybook stories / test import paths
- Run lint on touched files
Step 6 — Verify
- Typecheck clean
- Tests green
- No new circular deps (
madge --circular srcif available) - Bundle entry unchanged (no accidental public API leak)
Framework specifics
React + TypeScript
// features/orders/components/OrderList.tsx
export function OrderList(props: OrderListProps) { ... }
// features/orders/index.ts — public API
export { OrderList } from "./components/OrderList";
export type { OrderListProps } from "./components/OrderList";
- Prefer named exports for tree-shaking (match repo convention)
- Colocate
OrderList.test.tsxnext to component lazy()+Suspense: update import path only; don't change chunk names in same PR
Vue 2
- Move
.vue+ optional.jsmixin together - Register global components? Update
Vue.componentregistration path - Mixins: if extracting from mixin to composable (Vue 2.7), that's a separate task — this skill is move-only
Vue 3
<!-- features/orders/components/OrderList.vue -->
<script setup lang="ts">
import OrderRow from "./OrderRow.vue";
</script>
- Use
@/aliases consistently defineOptions({ name: 'OrderList' })when devtools name matters- Pinia store move: update
defineStoreid only if required by duplicate-id conflict
Splitting a large component
Order of extraction (safest first):
- Types / constants →
types.ts,constants.ts - Pure helpers →
utils.ts - Presentational subcomponents (props in, events out)
- Stateful logic → hook/composable
- Container stays thin
Each extraction = one mergeable step with typecheck + tests.
Output format (中文)
## 新结构
- 目录树或列表
## 公共 API
- 对外 export 清单
## 迁移说明
- 旧 import → 新 import 对照
## 验证
- typecheck / test / madge 结果
Anti-patterns
- ❌ Move + rename props in same commit
- ❌ Barrel file that re-exports entire subtree (kills tree-shaking)
- ❌
shared/importing fromfeatures/(wrong dependency direction) - ❌ Splitting without updating Storybook/tests
Related skills
- Same file, rename/simplify only →
behavior-preserving-refactor - Replace old module with new implementation →
strangler-refactor