agentsclimarketplace

Extract and move

Skill manman1414/frontend-refactor-skills/skills/extract-and-move

React/Vue/TS 前端重构 Agent Skills(行为不变重构、拆文件、绞杀者迁移)

Install
npx -y skills add manman1414/frontend-refactor-skills --skill extract-and-move

Assembled 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/ui or src/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 unitPublic exportKeep private
ComponentDefault or named exportInternal subcomponents
Hook/composableNamed useXxxHelper functions
Typesexport type only
Store (Pinia/Vuex/Zustand)Store factory or hookInternal actions

Step 3 — Pure move

  1. Create destination file(s) with identical content
  2. Update imports in moved file (paths only)
  3. Re-export from old path temporarily OR update all importers in one commit
  4. 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:

  1. Extract shared types to types.ts (no runtime imports)
  2. Extract pure utils (no component imports)
  3. 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 src if 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.tsx next to component
  • lazy() + Suspense: update import path only; don't change chunk names in same PR

Vue 2

  • Move .vue + optional .js mixin together
  • Register global components? Update Vue.component registration 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 defineStore id only if required by duplicate-id conflict

Splitting a large component

Order of extraction (safest first):

  1. Types / constantstypes.ts, constants.ts
  2. Pure helpersutils.ts
  3. Presentational subcomponents (props in, events out)
  4. Stateful logic → hook/composable
  5. 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 from features/ (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

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.