{"id":37956,"date":"2026-03-18T20:16:27","date_gmt":"2026-03-18T13:16:27","guid":{"rendered":"https:\/\/dps.media\/?p=37956"},"modified":"2026-03-18T20:25:33","modified_gmt":"2026-03-18T13:25:33","slug":"wordpress-plugin-dev-guide-2","status":"publish","type":"post","link":"https:\/\/dps.media\/zh\/wordpress-plugin-dev-guide-2\/","title":{"rendered":"WordPress \u63d2\u4ef6\u5f00\u53d1\u6307\u5357"},"content":{"rendered":"<?xml encoding=\"utf-8\" ?><style>\n@import url('https:\/\/fonts.googleapis.com\/css2?family=Syne:wght@600;700;800&family=JetBrains+Mono:wght@300;400;500&family=DM+Sans:wght@300;400;500&display=swap');\n\n#dps-guide {\n  --bg:      #09090e;\n  --bg2:     #0e0e18;\n  --faint:   #1a1a2c;\n  --border:  rgba(255,255,255,0.07);\n  --border2: rgba(255,255,255,0.13);\n  --text:    #ddddf0;\n  --muted:   #6060a0;\n  --blue:    #5b9cf6;\n  --green:   #34d399;\n  --purple:  #a78bfa;\n  --amber:   #fbbf24;\n  --slate:   #94a3b8;\n  --coral:   #fb7185;\n  --blue-bg:   rgba(91,156,246,0.08);\n  --green-bg:  rgba(52,211,153,0.08);\n  --purple-bg: rgba(167,139,250,0.08);\n  --amber-bg:  rgba(251,191,36,0.08);\n  --slate-bg:  rgba(148,163,184,0.08);\n  --coral-bg:  rgba(251,113,133,0.08);\n  background: var(--bg);\n  color: var(--text);\n  font-family: 'DM Sans', sans-serif;\n  line-height: 1.6;\n  border-radius: 16px;\n  overflow: hidden;\n  position: relative;\n}\n\n#dps-guide *,#dps-guide *::before,#dps-guide *::after{box-sizing:border-box;margin:0;padding:0;}\n\n\/* TOP BAR *\/\n#dps-guide .dps-topbar{background:rgba(9,9,14,0.92);backdrop-filter:blur(20px);border-bottom:1px solid var(--border);padding:0 40px;height:52px;display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:50;}\n#dps-guide .dps-brand{display:flex;align-items:center;gap:10px;text-decoration:none;}\n#dps-guide .dps-logo{width:28px;height:28px;border-radius:7px;background:linear-gradient(135deg,rgba(91,156,246,.35),rgba(167,139,250,.35));border:1px solid rgba(167,139,250,.25);display:flex;align-items:center;justify-content:center;font-family:'Syne',sans-serif;font-size:13px;font-weight:800;color:#c4b5f4;flex-shrink:0;}\n#dps-guide .dps-brand-name{font-family:'Syne',sans-serif;font-size:14px;font-weight:700;color:#fff;letter-spacing:-.01em;}\n#dps-guide .dps-topbar-right{display:flex;align-items:center;gap:14px;}\n#dps-guide .dps-nav-tag{font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--muted);letter-spacing:.04em;}\n#dps-guide #dps-copy-btn{display:flex;align-items:center;gap:7px;background:var(--faint);border:1px solid var(--border2);border-radius:8px;padding:6px 14px;cursor:pointer;font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--text);transition:all .18s;white-space:nowrap;}\n#dps-guide #dps-copy-btn:hover{background:rgba(255,255,255,0.06);border-color:rgba(255,255,255,0.2);}\n#dps-guide #dps-copy-btn.copied{background:rgba(52,211,153,0.08);border-color:rgba(52,211,153,.35);color:var(--green);}\n\n\/* PAGE *\/\n#dps-guide .dps-page{padding:48px 40px 64px;max-width:1080px;margin:0 auto;}\n\n\/* HEADER *\/\n#dps-guide .author-pill{display:inline-flex;align-items:center;gap:10px;background:var(--faint);border:1px solid var(--border2);border-radius:99px;padding:6px 14px 6px 8px;margin-bottom:28px;}\n#dps-guide .author-av{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,rgba(91,156,246,.4),rgba(167,139,250,.4));display:flex;align-items:center;justify-content:center;font-family:'Syne',sans-serif;font-size:12px;font-weight:800;color:#fff;}\n#dps-guide .author-pill span{font-size:13px;color:var(--text);font-weight:500;}\n#dps-guide .author-pill em{font-style:normal;color:var(--muted);font-size:12px;}\n#dps-guide h1{font-family:'Syne',sans-serif;font-size:clamp(34px,5vw,58px);font-weight:800;line-height:.95;letter-spacing:-.03em;color:#fff;margin-bottom:16px;}\n#dps-guide h1 span{background:linear-gradient(120deg,var(--blue) 0%,var(--purple) 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;}\n#dps-guide .header-sub{font-size:15px;font-weight:300;color:var(--muted);max-width:500px;margin-bottom:56px;}\n\n\/* SECTION LABEL *\/\n#dps-guide .slabel{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);display:flex;align-items:center;gap:10px;margin-bottom:20px;}\n#dps-guide .slabel::after{content:'';flex:1;height:1px;background:var(--border);}\n\n\/* TAGS *\/\n#dps-guide .tag{font-family:'JetBrains Mono',monospace;font-size:10px;font-weight:500;padding:3px 10px;border-radius:4px;border:1px solid;display:inline-flex;align-items:center;gap:6px;white-space:nowrap;}\n#dps-guide .tag .dot{width:5px;height:5px;border-radius:50%;background:currentColor;}\n#dps-guide .t-blue  {color:var(--blue);  background:var(--blue-bg);  border-color:rgba(91,156,246,.25);}\n#dps-guide .t-green {color:var(--green); background:var(--green-bg); border-color:rgba(52,211,153,.25);}\n#dps-guide .t-purple{color:var(--purple);background:var(--purple-bg);border-color:rgba(167,139,250,.25);}\n#dps-guide .t-amber {color:var(--amber); background:var(--amber-bg); border-color:rgba(251,191,36,.25);}\n#dps-guide .t-slate {color:var(--slate); background:var(--slate-bg); border-color:rgba(148,163,184,.25);}\n#dps-guide .t-coral {color:var(--coral); background:var(--coral-bg); border-color:rgba(251,113,133,.25);}\n\n\/* CARD *\/\n#dps-guide .card{background:var(--bg2);border:1px solid var(--border);border-radius:16px;overflow:hidden;}\n#dps-guide .card-pad{padding:28px;}\n\n\/* FILE TREE *\/\n#dps-guide .tree-section{margin-bottom:56px;}\n#dps-guide .tree-wrap{background:var(--bg2);border:1px solid var(--border);border-radius:16px;overflow:hidden;}\n#dps-guide .tree-topbar-inner{background:var(--faint);border-bottom:1px solid var(--border);padding:10px 20px;display:flex;align-items:center;gap:8px;}\n#dps-guide .tree-topbar-inner span{width:10px;height:10px;border-radius:50%;}\n#dps-guide .tree-topbar-inner small{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--muted);margin-left:8px;}\n#dps-guide .tree-body{display:grid;grid-template-columns:1fr 1fr;gap:0;}\n#dps-guide .tree-col{padding:24px 28px;}\n#dps-guide .tree-col+.tree-col{border-left:1px solid var(--border);}\n#dps-guide .tree-label{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin-bottom:14px;}\n#dps-guide .tree{font-family:'JetBrains Mono',monospace;font-size:12px;line-height:2.1;}\n#dps-guide .tree .d{color:var(--blue);font-weight:500;}\n#dps-guide .tree .f{color:var(--text);}\n#dps-guide .tree .x{color:var(--green);font-weight:500;}\n#dps-guide .tree .c{color:var(--muted);font-size:11px;}\n#dps-guide .tree .i{color:var(--coral);}\n#dps-guide .tree .indent{padding-left:20px;}\n#dps-guide .tree .indent2{padding-left:40px;}\n#dps-guide .tree .indent3{padding-left:60px;}\n\n\/* FLOW *\/\n#dps-guide .flow-section{margin-bottom:56px;}\n#dps-guide .flow-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;}\n#dps-guide .fcard{background:var(--bg2);border:1px solid var(--border);border-radius:16px;overflow:hidden;}\n#dps-guide .fcard-head{padding:20px 24px 0;}\n#dps-guide .fcard h3{font-family:'Syne',sans-serif;font-size:18px;font-weight:700;color:#fff;letter-spacing:-.01em;margin-bottom:4px;margin-top:10px;}\n#dps-guide .fcard-sub{font-size:12.5px;color:var(--muted);font-weight:300;margin-bottom:20px;}\n#dps-guide .fcard-body{padding:0 24px 24px;}\n#dps-guide .steps{display:flex;flex-direction:column;}\n#dps-guide .step{display:flex;gap:14px;align-items:flex-start;}\n#dps-guide .step-l{display:flex;flex-direction:column;align-items:center;flex-shrink:0;}\n#dps-guide .step-dot{width:28px;height:28px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-family:'JetBrains Mono',monospace;font-size:11px;font-weight:500;border:1px solid;flex-shrink:0;}\n#dps-guide .step-line{width:1px;flex:1;min-height:14px;background:var(--border);margin:3px 0;}\n#dps-guide .step-r{padding-top:4px;padding-bottom:18px;}\n#dps-guide .step-title{font-size:13px;font-weight:500;color:var(--text);margin-bottom:2px;}\n#dps-guide .step-desc{font-size:12px;color:var(--muted);font-weight:300;line-height:1.55;}\n#dps-guide .code{margin-top:6px;background:var(--faint);border-radius:6px;padding:7px 12px;font-family:'JetBrains Mono',monospace;font-size:11px;line-height:1.9;}\n#dps-guide .code .cmd{color:var(--green);}\n#dps-guide .code .cmt{color:var(--muted);}\n#dps-guide .code .val{color:var(--amber);}\n#dps-guide .code .key{color:var(--blue);}\n\n\/* SCRIPTS *\/\n#dps-guide .scripts-section{margin-bottom:56px;}\n#dps-guide .scripts-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;}\n#dps-guide .scmd{background:var(--bg2);border:1px solid var(--border);border-radius:12px;padding:18px 20px;transition:border-color .2s;}\n#dps-guide .scmd:hover{border-color:var(--border2);}\n#dps-guide .scmd-cmd{font-family:'JetBrains Mono',monospace;font-size:13px;font-weight:500;color:var(--green);margin-bottom:6px;}\n#dps-guide .scmd-what{font-size:12.5px;color:var(--muted);font-weight:300;line-height:1.5;margin-bottom:8px;}\n#dps-guide .scmd-detail{font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--muted);border-top:1px solid var(--border);padding-top:8px;line-height:1.7;}\n\n\/* DO\/DONT *\/\n#dps-guide .dodonts{display:grid;grid-template-columns:1fr 1fr;gap:2px;border-radius:12px;overflow:hidden;border:1px solid var(--border);}\n#dps-guide .do-col{background:rgba(52,211,153,.04);padding:20px 22px;}\n#dps-guide .dont-col{background:rgba(251,113,133,.04);padding:20px 22px;}\n#dps-guide .do-head{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--green);margin-bottom:12px;display:flex;align-items:center;gap:8px;}\n#dps-guide .dont-head{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--coral);margin-bottom:12px;display:flex;align-items:center;gap:8px;}\n#dps-guide .do-head::before{content:'\u2713';font-size:12px;}\n#dps-guide .dont-head::before{content:'\u2717';font-size:12px;}\n#dps-guide .do-item,#dps-guide .dont-item{font-family:'JetBrains Mono',monospace;font-size:11.5px;padding:6px 10px;border-radius:6px;margin-bottom:4px;line-height:1.5;}\n#dps-guide .do-item{color:var(--green);background:rgba(52,211,153,.06);}\n#dps-guide .dont-item{color:var(--coral);background:rgba(251,113,133,.06);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);}\n\n\/* ZIP *\/\n#dps-guide .zip-section{margin-bottom:56px;}\n#dps-guide .zip-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;}\n#dps-guide .zip-card{background:var(--bg2);border:1px solid var(--border);border-radius:14px;overflow:hidden;}\n#dps-guide .zip-head{padding:14px 18px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:10px;}\n#dps-guide .zip-body{padding:14px 18px;}\n#dps-guide .zip-row{display:flex;align-items:center;justify-content:space-between;padding:7px 0;border-bottom:1px solid var(--border);}\n#dps-guide .zip-row:last-child{border-bottom:none;}\n#dps-guide .zip-path{font-family:'JetBrains Mono',monospace;font-size:11.5px;}\n#dps-guide .zip-note{font-size:11px;color:var(--muted);font-weight:300;}\n\n\/* ACCEPTANCE *\/\n#dps-guide .ac-section{margin-bottom:56px;}\n#dps-guide .ac-list{display:flex;flex-direction:column;gap:6px;}\n#dps-guide .ac-item{display:flex;align-items:center;gap:14px;background:var(--bg2);border:1px solid var(--border);border-radius:10px;padding:12px 18px;transition:border-color .2s;}\n#dps-guide .ac-item:hover{border-color:var(--border2);}\n#dps-guide .ac-check{width:20px;height:20px;border-radius:6px;border:1px solid rgba(52,211,153,.3);background:rgba(52,211,153,.06);display:flex;align-items:center;justify-content:center;font-size:11px;color:var(--green);flex-shrink:0;}\n#dps-guide .ac-text{font-size:13px;color:var(--text);font-weight:400;}\n\n\/* BOTTOM BAR *\/\n#dps-guide .dps-footer{border-top:1px solid var(--border);padding:22px 40px;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:12px;}\n#dps-guide .dps-footer-l{display:flex;align-items:center;gap:10px;}\n#dps-guide .dps-footer p{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--muted);}\n#dps-guide .dps-footer-links{display:flex;gap:20px;}\n#dps-guide .dps-footer-links a{font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--muted);text-decoration:none;}\n#dps-guide .dps-footer-links a:hover{color:var(--text);}\n\n\/* FADE *\/\n#dps-guide .fi{opacity:0;transform:translateY(18px);transition:opacity .5s ease,transform .5s ease;}\n#dps-guide .fi.in{opacity:1;transform:none;}\n\n@media(max-width:720px){\n  #dps-guide .dps-topbar{padding:0 20px;}\n  #dps-guide .dps-nav-tag{display:none;}\n  #dps-guide .dps-page{padding:32px 20px 48px;}\n  #dps-guide .tree-body,#dps-guide .flow-grid,#dps-guide .scripts-grid,#dps-guide .zip-grid,#dps-guide .dodonts{grid-template-columns:1fr;}\n  #dps-guide .tree-col+.tree-col{border-left:none;border-top:1px solid var(--border);}\n  #dps-guide .dps-footer{padding:20px;}\n}\n<\/style><div id=\"dps-guide\">\n\n  <!-- TOP BAR -->\n  <div class=\"dps-topbar\">\n    <div class=\"dps-brand\">\n      <div class=\"dps-logo\">D<\/div>\n      <span class=\"dps-brand-name\">DPS\u5a92\u4f53<\/span>\n    <\/div>\n    <div class=\"dps-topbar-right\">\n      <span class=\"dps-nav-tag\">WP \u63d2\u4ef6\u5f00\u53d1\u6307\u5357 \u2014 \u5185\u90e8<\/span>\n      <button id=\"dps-copy-btn\">\n        <svg width=\"13\" height=\"13\" viewbox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"5\" y=\"5\" width=\"9\" height=\"9\" rx=\"2\"><\/rect><path d=\"M11 5V3a2 2 0 0 0-2-2H3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2\"><\/path><\/svg>\n        <span id=\"dps-copy-label\">\u590d\u5236 Agent \u63d0\u793a\u8bcd<\/span>\n      <\/button>\n    <\/div>\n  <\/div>\n\n  <div class=\"dps-page\">\n\n    <!-- HEADER -->\n    <div class=\"fi\">\n      <div class=\"author-pill\">\n        <div class=\"author-av\">H<\/div>\n        <span>Hi\u1ec3n<\/span>\n        <em>CEO \u00b7 DPS.MEDIA<\/em>\n      <\/div>\n      <h1>WordPress<br><span>\u63d2\u4ef6\u5f00\u53d1<\/span><br>\u6307\u5357<\/h1>\n      <p class=\"header-sub\">\u56e2\u961f\u7684 source \u2192 build \u2192 release \u6d41\u7a0b\u3002\u8db3\u4ee5\u652f\u6301\u672c\u5730\u5f00\u53d1\u3001\u6253\u5305 ZIP\u3001\u5b89\u88c5\u5230 WordPress \u751f\u4ea7\u73af\u5883\u3002.<\/p>\n    <\/div>\n\n    <!-- STACK PILLS -->\n    <div class=\"fi\" style=\"display:flex;gap:8px;flex-wrap:wrap;margin-bottom:56px;\">\n      <span class=\"tag t-blue\"><span class=\"dot\"><\/span>PHP 8.x<\/span>\n      <span class=\"tag t-blue\"><span class=\"dot\"><\/span>WordPress hooks API<\/span>\n      <span class=\"tag t-green\"><span class=\"dot\"><\/span>@wordpress\/scripts<\/span>\n      <span class=\"tag t-green\"><span class=\"dot\"><\/span>React (\u7ba1\u7406\u540e\u53f0 UI)<\/span>\n      <span class=\"tag t-green\"><span class=\"dot\"><\/span>Webpack 5<\/span>\n      <span class=\"tag t-amber\"><span class=\"dot\"><\/span>npm \u811a\u672c<\/span>\n      <span class=\"tag t-slate\"><span class=\"dot\"><\/span>Node.js \u2265 18<\/span>\n      <span class=\"tag t-slate\"><span class=\"dot\"><\/span>ZIP \u53d1\u5e03\u5305<\/span>\n    <\/div>\n\n    <!-- FILE TREE -->\n    <div class=\"tree-section fi\">\n      <div class=\"slabel\">\u76ee\u5f55\u7ed3\u6784<\/div>\n      <div class=\"tree-wrap\">\n        <div class=\"tree-topbar-inner\">\n          <span style=\"background:#ff5f57;\"><\/span>\n          <span style=\"background:#febc2e;\"><\/span>\n          <span style=\"background:#28c840;\"><\/span>\n          <small>my-plugin\/ \u2014 \u9879\u76ee\u6839\u76ee\u5f55<\/small>\n        <\/div>\n        <div class=\"tree-body\">\n          <div class=\"tree-col\">\n            <div class=\"tree-label\">\u6e90\u7801 (\u5f00\u53d1)<\/div>\n            <div class=\"tree\">\n              <div><span class=\"d\">my-plugin.php<\/span> <span class=\"c\">\u2190 \u4e3b\u63d2\u4ef6\u6587\u4ef6<\/span><\/div>\n              <div class=\"indent\"><span class=\"d\">includes\/<\/span> <span class=\"c\">\u2190 PHP \u8fd0\u884c\u65f6<\/span><\/div>\n              <div class=\"indent2\"><span class=\"f\">class-core.php<\/span><\/div>\n              <div class=\"indent2\"><span class=\"f\">class-admin.php<\/span><\/div>\n              <div class=\"indent\"><span class=\"d\">admin\/<\/span><\/div>\n              <div class=\"indent2\"><span class=\"d\" style=\"color:var(--amber);\">src\/<\/span> <span class=\"c\">\u2190 \u5728\u6b64\u5904\u7f16\u5199\u4ee3\u7801<\/span><\/div>\n              <div class=\"indent3\"><span class=\"x\">index.js<\/span> <span class=\"c\">\u2190 \u5165\u53e3\u70b9<\/span><\/div>\n              <div class=\"indent3\"><span class=\"f\">components\/<\/span><\/div>\n              <div class=\"indent2\"><span class=\"d\" style=\"color:var(--green);\">dist\/<\/span> <span class=\"c\">\u2190 \u6784\u5efa\u8f93\u51fa<\/span><\/div>\n              <div class=\"indent3\"><span class=\"x\">index.js<\/span><\/div>\n              <div class=\"indent3\"><span class=\"x\">index.asset.php<\/span><\/div>\n              <div class=\"indent3\"><span class=\"f\">index.css<\/span><\/div>\n              <div class=\"indent\"><span class=\"f\">languages\/<\/span> <span class=\"c\">\u2190 \u56fd\u9645\u5316<\/span><\/div>\n              <div class=\"indent\"><span class=\"i\">node_modules\/<\/span> <span class=\"c\">\u2190 .gitignore<\/span><\/div>\n              <div class=\"indent\"><span class=\"i\">releases\/<\/span> <span class=\"c\">\u2190 .gitignore<\/span><\/div>\n            <\/div>\n          <\/div>\n          <div class=\"tree-col\">\n            <div class=\"tree-label\">\u914d\u7f6e\u6587\u4ef6<\/div>\n            <div class=\"tree\">\n              <div><span class=\"x\">package.json<\/span><\/div>\n              <div><span class=\"f\">webpack.config.js<\/span> <span class=\"c\">\u2190 \u5982\u6709\u81ea\u5b9a\u4e49\u9700\u6c42<\/span><\/div>\n              <div><span class=\"x\">.gitignore<\/span><\/div>\n              <div><span class=\"x\">BUILD.md<\/span><\/div>\n              <div><span class=\"f\">readme.txt<\/span><\/div>\n              <div><span class=\"f\">uninstall.php<\/span><\/div>\n              <div style=\"margin-top:16px;background:var(--faint);border-radius:8px;padding:12px 14px;border:1px solid var(--border);\">\n                <div style=\"color:var(--muted);\">\/\/ \u2713 \u6b63\u786e \u2014 \u4ece dist \u52a0\u8f7d<\/div>\n                <div style=\"color:var(--green);\">plugins_url(<span style=\"color:var(--amber);\">\u2018admin\/dist\/index.js\u2019<\/span>)<\/div>\n                <div style=\"color:var(--muted);margin-top:8px;\">\/\/ \u2717 \u9519\u8bef \u2014 \u4e0d\u8981\u4ece src \u52a0\u8f7d<\/div>\n                <div style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.5);\">plugins_url(<span style=\"color:var(--amber);\">\u2018admin\/src\/index.js\u2019<\/span>)<\/div>\n              <\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- WORKFLOWS -->\n    <div class=\"flow-section fi\">\n      <div class=\"slabel\">\u5de5\u4f5c\u6d41<\/div>\n      <div class=\"flow-grid\">\n        <div class=\"fcard\">\n          <div class=\"fcard-head\">\n            <div class=\"tag t-green\"><span class=\"dot\"><\/span>\u672c\u5730\u5f00\u53d1<\/div>\n            <h3>\u672c\u5730\u5f00\u53d1<\/h3>\n            <p class=\"fcard-sub\">\u8fd0\u884c watch \u6a21\u5f0f\uff0c\u4fee\u6539 JS\/React \u2192 \u81ea\u52a8\u6784\u5efa\uff0cF5 \u5237\u65b0 WP \u5373\u53ef\u7acb\u5373\u770b\u5230\u6548\u679c\u3002.<\/p>\n          <\/div>\n          <div class=\"fcard-body\">\n            <div class=\"steps\">\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-green\">01<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">\u5b89\u88c5\u4f9d\u8d56<\/div><div class=\"step-desc\">\u53ea\u9700\u9996\u6b21\u3002\u8981\u6c42 Node.js \u2265 18\u3002.<\/div><div class=\"code\"><span class=\"cmd\">npm install<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-green\">02<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">\u542f\u7528 watch \u6a21\u5f0f<\/div><div class=\"step-desc\">Webpack \u76d1\u542c\uff1a\u5728 \u4e2d\u4fdd\u5b58\u6587\u4ef6 <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--amber);\" data-no-translation=\"\">admin\/src\/<\/code> \u2192 \u81ea\u52a8\u6784\u5efa\u5230 <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--green);\" data-no-translation=\"\">admin\/dist\/<\/code>. \u5728 WP \u4e2d\u9700\u8981\u624b\u52a8\u6309 F5\u3002.<\/div><div class=\"code\"><span class=\"cmd\">npm run start<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-green\">03<\/div><\/div><div class=\"step-r\"><div class=\"step-title\">\u5728\u672c\u5730 WP \u4e0a\u6d4b\u8bd5<\/div><div class=\"step-desc\">\u521b\u5efa\u7b26\u53f7\u94fe\u63a5\u5230 <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--slate);\" data-no-translation=\"\">wp-content\/plugins\/<\/code> \u6216\u4f7f\u7528 Local by Flywheel\u3002.<\/div><\/div><\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n        <div class=\"fcard\">\n          <div class=\"fcard-head\">\n            <div class=\"tag t-amber\"><span class=\"dot\"><\/span>Build &amp; Release<\/div>\n            <h3>\u6253\u5305 ZIP\uff0c\u5b89\u88c5 WP<\/h3>\n            <p class=\"fcard-sub\">\u6784\u5efa\u751f\u4ea7\u7248\uff0c\u6253\u5305\u5e72\u51c0\u7684 ZIP \u2014\u2014 \u670d\u52a1\u5668\u4e0a\u65e0\u9700 npm\u3002.<\/p>\n          <\/div>\n          <div class=\"fcard-body\">\n            <div class=\"steps\">\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-amber\">01<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">\u751f\u4ea7\u73af\u5883\u6784\u5efa<\/div><div class=\"step-desc\">Webpack \u6784\u5efa\uff0c\u5305\u542b\u538b\u7f29 + tree-shaking\u3002.<\/div><div class=\"code\"><span class=\"cmd\">npm run build<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-amber\">02<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">\u6253\u5305 ZIP<\/div><div class=\"step-desc\">\u811a\u672c\u590d\u5236\u6b63\u786e\u6587\u4ef6\uff0c\u6392\u9664 <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--coral);\" data-no-translation=\"\">node_modules<\/code> v\u00e0 <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--coral);\" data-no-translation=\"\">admin\/src<\/code>.<\/div><div class=\"code\"><span class=\"cmd\">npm run package<\/span><br><span class=\"cmt\"># \u2192 releases\/plugin-v1.0.0.zip<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-amber\">03<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">\u6821\u9a8c SHA256<\/div><div class=\"code\"><span class=\"cmd\">sha256sum<\/span> <span class=\"val\">releases\/plugin-v1.0.0.zip<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot\" style=\"color:var(--green);background:var(--green-bg);border-color:rgba(52,211,153,.25);\">\u2713<\/div><\/div><div class=\"step-r\"><div class=\"step-title\" style=\"color:var(--green);\">\u4e0a\u4f20\u5230 WordPress<\/div><div class=\"step-desc\">Admin \u2192 Plugins \u2192 Add New \u2192 Upload\u3002\u6fc0\u6d3b\u3002\u670d\u52a1\u5668\u4e0a\u65e0\u9700 npm\u3002.<\/div><\/div><\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- NPM SCRIPTS -->\n    <div class=\"scripts-section fi\">\n      <div class=\"slabel\">npm \u811a\u672c \u2014 \u5907\u5fd8\u5355<\/div>\n      <div class=\"scripts-grid\">\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run start<\/div><div class=\"scmd-what\">\u76d1\u542c\u6a21\u5f0f \u2014 \u65e5\u5e38\u5f00\u53d1<\/div><div class=\"scmd-detail\">webpack \u2013watch \u2013mode development<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run build<\/div><div class=\"scmd-what\">\u751f\u4ea7\u6784\u5efa \u2014 \u53d1\u5e03\u524d<\/div><div class=\"scmd-detail\">webpack \u2013mode production + minify<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run package<\/div><div class=\"scmd-what\">\u6253\u5305\u5e72\u51c0\u7684 ZIP \u5230 releases\/<\/div><div class=\"scmd-detail\">\u6392\u9664 src\/ node_modules\/ .git\/<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run lint:js<\/div><div class=\"scmd-what\">\u9075\u5faa WP \u6807\u51c6\u7684 JS \u4ee3\u7801\u68c0\u67e5<\/div><div class=\"scmd-detail\">wp-scripts lint-js<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run format<\/div><div class=\"scmd-what\">\u81ea\u52a8\u683c\u5f0f\u5316\u4ee3\u7801<\/div><div class=\"scmd-detail\">wp-scripts format (prettier)<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run release<\/div><div class=\"scmd-what\">Lint \u2192 \u6784\u5efa \u2192 \u6253\u5305<\/div><div class=\"scmd-detail\">\u5728\u4e00\u6761\u547d\u4ee4\u4e2d\u6267\u884c\u68c0\u67e5 + \u6784\u5efa + \u6253\u5305<\/div><\/div>\n      <\/div>\n    <\/div>\n\n    <!-- ZIP CONTENTS -->\n    <div class=\"zip-section fi\">\n      <div class=\"slabel\">ZIP \u53d1\u5e03\u5305 \u2014 \u5185\u90e8\u4e0e\u5916\u90e8<\/div>\n      <div class=\"zip-grid\">\n        <div class=\"zip-card\">\n          <div class=\"zip-head\"><span class=\"tag t-green\"><span class=\"dot\"><\/span>\u2713 ZIP \u5305\u4e2d\u5305\u542b<\/span><\/div>\n          <div class=\"zip-body\">\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">my-plugin.php<\/span><span class=\"zip-note\">\u4e3b\u63d2\u4ef6\u6587\u4ef6<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">includes\/<\/span><span class=\"zip-note\">\u5b8c\u6574\u7684 PHP \u8fd0\u884c\u65f6\u6587\u4ef6<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">admin\/dist\/<\/span><span class=\"zip-note\">\u5df2\u6784\u5efa\u597d\u7684 JS\/CSS<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">languages\/<\/span><span class=\"zip-note\">i18n \u8bed\u8a00\u5305\uff08\u5982\u6709\uff09<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">readme.txt<\/span><span class=\"zip-note\">WP.org \u683c\u5f0f<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">uninstall.php<\/span><span class=\"zip-note\">\u5220\u9664\u63d2\u4ef6\u65f6\u7684\u6e05\u7406\u811a\u672c<\/span><\/div>\n          <\/div>\n        <\/div>\n        <div class=\"zip-card\">\n          <div class=\"zip-head\"><span class=\"tag t-coral\"><span class=\"dot\"><\/span>\u2717 ZIP \u5305\u4e2d\u4e0d\u5305\u542b<\/span><\/div>\n          <div class=\"zip-body\">\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">node_modules\/<\/span><span class=\"zip-note\">\u4f9d\u8d56\u4ec5\u7528\u4e8e\u5f00\u53d1<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">admin\/src\/<\/span><span class=\"zip-note\">\u6e90\u7801\uff0c\u4e0d\u8fd0\u884c<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">.git\/<\/span><span class=\"zip-note\">\u4ed3\u5e93\u5143\u6570\u636e<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">package.json \/ webpack.config.js<\/span><span class=\"zip-note\">\u6784\u5efa\u914d\u7f6e<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">.test.js \/ debug-.php<\/span><span class=\"zip-note\">\u5185\u90e8\u6d4b\u8bd5\u6587\u4ef6<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">.env \/ .DS_Store<\/span><span class=\"zip-note\">\u672c\u5730\u673a\u5668\u6587\u4ef6<\/span><\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- DO \/ DON'T -->\n    <div class=\"fi\" style=\"margin-bottom:56px;\">\n      <div class=\"slabel\">\u91cd\u8981\u89c4\u5219<\/div>\n      <div class=\"dodonts\">\n        <div class=\"do-col\">\n          <div class=\"do-head\">\u6b63\u786e\u505a\u6cd5<\/div>\n          <div class=\"do-item\">\u5165\u961f\u81ea <code style=\"font-family:'JetBrains Mono',monospace;\" data-no-translation=\"\">admin\/dist\/<\/code><\/div>\n          <div class=\"do-item\">\u8bfb\u53d6 <code style=\"font-family:'JetBrains Mono',monospace;\" data-no-translation=\"\">index.asset.php<\/code> \u83b7\u53d6\u4f9d\u8d56 + \u7248\u672c<\/div>\n          <div class=\"do-item\">\u4f7f\u7528 <code style=\"font-family:'JetBrains Mono',monospace;\" data-no-translation=\"\">wp_localize_script()<\/code> \u4f20\u9012\u6570\u636e PHP \u2192 JS<\/div>\n          <div class=\"do-item\">\u5f00\u5c55 <code style=\"font-family:'JetBrains Mono',monospace;\" data-no-translation=\"\">npm run build<\/code> \u4e4b\u524d <code style=\"font-family:'JetBrains Mono',monospace;\" data-no-translation=\"\">npm run package<\/code><\/div>\n          <div class=\"do-item\">\u6309\u6761\u4ef6\u52a0\u8f7d \u2014\u2014 \u4ec5\u5728\u9700\u8981\u7684\u9875\u9762 enqueue<\/div>\n          <div class=\"do-item\">\u5168\u90e8\u6dfb\u52a0\u524d\u7f00\uff1a <code style=\"font-family:'JetBrains Mono',monospace;\" data-no-translation=\"\">dps_<\/code>, <code style=\"font-family:'JetBrains Mono',monospace;\" data-no-translation=\"\">DPS_<\/code><\/div>\n        <\/div>\n        <div class=\"dont-col\">\n          <div class=\"dont-head\">\u4e0d\u8981\u505a<\/div>\n          <div class=\"dont-item\">\u5165\u961f\u81ea <code style=\"font-family:'JetBrains Mono',monospace;\" data-no-translation=\"\">admin\/src\/<\/code><\/div>\n          <div class=\"dont-item\">\u5728 PHP \u4e2d\u786c\u7f16\u7801\u7248\u672c\u54c8\u5e0c<\/div>\n          <div class=\"dont-item\">\u4e3a\u4e86 <code style=\"font-family:'JetBrains Mono',monospace;\" data-no-translation=\"\">node_modules\/<\/code> \u5728 ZIP \u4e2d<\/div>\n          <div class=\"dont-item\">\u5728\u751f\u4ea7\u670d\u52a1\u5668\u4e0a\u6267\u884c npm install<\/div>\n          <div class=\"dont-item\">\u5728\u6b64\u5904\u6267\u884c\u91cd\u91cf\u7ea7 DB \u67e5\u8be2 <code style=\"font-family:'JetBrains Mono',monospace;\" data-no-translation=\"\">init<\/code> \u94a9\u5b50<\/div>\n          <div class=\"dont-item\"><code style=\"font-family:'JetBrains Mono',monospace;\" data-no-translation=\"\">echo $_POST['x']<\/code> \u672a\u8fdb\u884c sanitize\/escape<\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- CHECKLIST -->\n    <div class=\"ac-section fi\">\n      <div class=\"slabel\">\u751f\u4ea7\u5c31\u7eea\u6e05\u5355<\/div>\n      <div style=\"display:grid;grid-template-columns:1fr 1fr;gap:6px;\">\n        <div style=\"display:flex;flex-direction:column;gap:6px;\">\n          <div style=\"font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--blue);padding:4px 0 8px;\">Build &amp; Release<\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\"><code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\" data-no-translation=\"\">npm run build<\/code> \u65e0\u9519\u8bef \u2192 <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\" data-no-translation=\"\">admin\/dist\/<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">ZIP \u53ef\u5b89\u88c5\uff0c\u6fc0\u6d3b\u65e0\u9519\u8bef \u2014\u2014 \u65e0\u9700 npm \u670d\u52a1\u5668<\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">ZIP \u4e0d\u5305\u542b <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--coral);\" data-no-translation=\"\">node_modules\/<\/code> \u8fd8\u662f <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--coral);\" data-no-translation=\"\">src\/<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u53cd\u9988\uff1a\u6587\u4ef6\u5217\u8868 + ZIP \u8def\u5f84 + SHA256<\/div><\/div>\n          <div style=\"font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--purple);padding:12px 0 8px;\">\u5b89\u5168<\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u6240\u6709 PHP \u6587\u4ef6\u90fd\u6709 <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--purple);\" data-no-translation=\"\">if (!defined('ABSPATH')) exit;<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u6240\u6709 AJAX\/form\uff1anonce \u6821\u9a8c + <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--purple);\" data-no-translation=\"\">current_user_can()<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u8f93\u5165\u5df2\u6e05\u7406\uff0c\u8f93\u51fa\u5df2\u8f6c\u4e49<\/div><\/div>\n        <\/div>\n        <div style=\"display:flex;flex-direction:column;gap:6px;\">\n          <div style=\"font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--amber);padding:4px 0 8px;\">\u6548\u679c<\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u8d44\u6e90\u6309\u6761\u4ef6\u52a0\u8f7d \u2014\u2014 \u4e0d\u5728\u5168\u7ad9\u52a0\u8f7d<\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u811a\u672c\uff1a <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--amber);\" data-no-translation=\"\">in_footer: true<\/code> + <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--amber);\" data-no-translation=\"\">strategy: defer<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u4e0d\u8981\u5728\u6b64\u5904\u6267\u884c\u91cd\u91cf\u7ea7 DB \u67e5\u8be2 <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--amber);\" data-no-translation=\"\">init<\/code> \u94a9\u5b50<\/div><\/div>\n          <div style=\"font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--green);padding:12px 0 8px;\">\u89c4\u8303<\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u6240\u6709 function\/class\/option \u90fd\u6709\u524d\u7f00 <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\" data-no-translation=\"\">dps_<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u63d2\u4ef6\u5934\uff1a <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\" data-no-translation=\"\">Requires at least<\/code>, <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\" data-no-translation=\"\">Requires PHP<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u6240\u6709\u5b57\u7b26\u4e32\u4f7f\u7528 i18n\uff0c, <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\" data-no-translation=\"\">uninstall.php<\/code> \u6e05\u7406\u5e72\u51c0<\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\"><code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\" data-no-translation=\"\">BUILD.md<\/code> \u5b8c\u6574\uff1ainstall, build, package, test<\/div><\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n  <\/div><!-- \/dps-page -->\n\n  <!-- BOTTOM BAR -->\n  <div class=\"dps-footer\">\n    <div class=\"dps-footer-l\">\n      <div class=\"dps-logo\">D<\/div>\n      <p>DPS.MEDIA \u80a1\u4efd\u516c\u53f8 \u00b7 \u7a0e\u53f7 0318700500<\/p>\n    <\/div>\n    <div class=\"dps-footer-links\">\n      <a href=\"mailto:marketing@dps.media\">marketing@dps.media<\/a>\n      <a href=\"tel:0961545445\">0961 545 445<\/a>\n      <a href=\"https:\/\/dps.media\/zh\/\">dps.media<\/a>\n    <\/div>\n  <\/div>\n\n<\/div><!-- \/#dps-guide --><script>\n(function(){\n  var guide = document.getElementById('dps-guide');\n  if(!guide) return;\n\n  \/\/ Fade-in on scroll\n  var io = new IntersectionObserver(function(es){\n    es.forEach(function(e){ if(e.isIntersecting){ e.target.classList.add('in'); io.unobserve(e.target); } });\n  },{threshold:0.05});\n  guide.querySelectorAll('.fi').forEach(function(el,i){\n    el.style.transitionDelay=(i*0.06)+'s';\n    io.observe(el);\n  });\n\n  \/\/ Copy button\n  var btn = document.getElementById('dps-copy-btn');\n  var lbl = document.getElementById('dps-copy-label');\n  if(!btn) return;\n\n  btn.addEventListener('click', function(){\n    var md = \"# WP Plugin Dev \\u2014 Agent Prompt (DPS.MEDIA)\\n\\n## M\\u1ee5c ti\\u00eau\\nRefactor plugin sang flow **source \\u2192 build \\u2192 release**. Plugin ph\\u1ea3i: load nhanh, kh\\u00f4ng conflict, \\u0111\\u00fang WP coding standards, b\\u1ea3o m\\u1eadt, d\\u1ec5 b\\u1ea3o tr\\u00ec.\\n\\n---\\n\\n## 0. \\u0110\\u00e1nh gi\\u00e1 tr\\u01b0\\u1edbc khi b\\u1eaft \\u0111\\u1ea7u (YAGNI check)\\n\\nTr\\u01b0\\u1edbc khi refactor b\\u1ea5t k\\u1ef3 th\\u1ee9 g\\u00ec, ki\\u1ec3m tra t\\u1eebng th\\u01b0 m\\u1ee5c asset v\\u00e0 t\\u1ef1 \\u0111\\u00e1nh gi\\u00e1:\\n\\n- `admin\/` \\u2014 c\\u00f3 React\/JSX\/TS, import ES module, Sass? \\u2192 \\u0111\\u01b0a v\\u00e0o pipeline\\n- `public\/` \\u2014 ch\\u1ec9 vanilla JS\/jQuery\/CSS thu\\u1ea7n? \\u2192 gi\\u1eef static, kh\\u00f4ng build\\n\\n\\u00c1p d\\u1ee5ng **YAGNI** \\u2014 ch\\u1ec9 build nh\\u1eefng g\\u00ec th\\u1ef1c s\\u1ef1 c\\u1ea7n transpile. B\\u00e1o l\\u1ea1i quy\\u1ebft \\u0111\\u1ecbnh tr\\u01b0\\u1edbc khi vi\\u1ebft code.\\n\\n---\\n\\n## 1. C\\u1ea5u tr\\u00fac th\\u01b0 m\\u1ee5c\\n```\\nmy-plugin\/\\n\\u251c\\u2500\\u2500 my-plugin.php\\n\\u251c\\u2500\\u2500 includes\/\\n\\u251c\\u2500\\u2500 admin\/\\n\\u2502   \\u251c\\u2500\\u2500 src\/     \\u2190 vi\\u1ebft code \\u1edf \\u0111\\u00e2y\\n\\u2502   \\u2514\\u2500\\u2500 dist\/    \\u2190 PHP enqueue t\\u1eeb \\u0111\\u00e2y\\n\\u251c\\u2500\\u2500 languages\/\\n\\u251c\\u2500\\u2500 releases\/  (.gitignore)\\n\\u251c\\u2500\\u2500 package.json\\n\\u251c\\u2500\\u2500 .gitignore\\n\\u2514\\u2500\\u2500 BUILD.md\\n```\\n\\n## 2. Plugin file header\\n```php\\n\/**\\n * Plugin Name: My Plugin\\n * Requires at least: 6.0\\n * Requires PHP: 8.0\\n * Tested up to: 6.7\\n * Text Domain: my-plugin\\n *\/\\nif (!defined('ABSPATH')) exit;\\n```\\n\\n## 3. npm scripts\\n```json\\n{\\n  \\\"start\\\":   \\\"wp-scripts start\\\",\\n  \\\"build\\\":   \\\"wp-scripts build\\\",\\n  \\\"package\\\": \\\"node scripts\/package.js\\\",\\n  \\\"lint:js\\\": \\\"wp-scripts lint-js admin\/src\\\",\\n  \\\"check\\\":   \\\"npm run lint:js && npm run lint:css\\\",\\n  \\\"release\\\": \\\"npm run check && npm run build && npm run package\\\"\\n}\\n```\\n\\n## 4. PHP enqueue \\u2014 chu\\u1ea9n\\n```php\\nadd_action('admin_enqueue_scripts', function($hook) {\\n  if ($hook !== 'toplevel_page_my-plugin') return; \/\/ conditional\\n  $asset = include plugin_dir_path(__FILE__) . 'admin\/dist\/index.asset.php';\\n  wp_enqueue_script('my-plugin', plugins_url('admin\/dist\/index.js', __FILE__),\\n    $asset['dependencies'], $asset['version'],\\n    ['in_footer' => true, 'strategy' => 'defer']);\\n  wp_localize_script('my-plugin', 'dpsData', [\\n    'nonce' => wp_create_nonce('dps_nonce')\\n  ]);\\n});\\n```\\n\\n## 5. Security\\n```php\\n\/\/ \\u0110\\u1ea7u m\\u1ecdi file PHP\\nif (!defined('ABSPATH')) exit;\\n\\n\/\/ Prefix t\\u1ea5t c\\u1ea3\\nfunction dps_get_settings() {}\\nclass DPS_Plugin_Core {}\\n\\n\/\/ AJAX handler\\nfunction dps_handle_ajax() {\\n  check_ajax_referer('dps_nonce', 'nonce');\\n  if (!current_user_can('manage_options')) wp_die('Unauthorized', 403);\\n  $name = sanitize_text_field($_POST['name']);\\n  echo esc_html($name);\\n  wp_die();\\n}\\n```\\n\\n## 6. ZIP release\\nCo trong ZIP: my-plugin.php, includes\/, admin\/dist\/, languages\/, readme.txt, uninstall.php\\nKHONG co: node_modules\/, admin\/src\/, .git\/, package.json, *.test.js\\n\\n## 7. Acceptance criteria\\n- [ ] npm run build khong loi, output ra admin\/dist\/\\n- [ ] ZIP cai duoc, Activate khong loi, khong can npm tren server\\n- [ ] ZIP khong chua node_modules\/ hay admin\/src\/\\n- [ ] Bao lai: danh sach file + ZIP path + SHA256\\n- [ ] Moi file PHP co: if (!defined('ABSPATH')) exit;\\n- [ ] Moi AJAX\/form: nonce verify + current_user_can()\\n- [ ] Input sanitized, output escaped\\n- [ ] Asset load conditional, script defer\\n- [ ] Prefix dps_ cho moi function\/class\/option\\n- [ ] Plugin header day du fields\\n- [ ] uninstall.php cleanup sach\\n- [ ] BUILD.md day du\\n\";\n\n    try {\n      var ta = document.createElement('textarea');\n      ta.value = md;\n      ta.style.cssText = 'position:fixed;top:-9999px;left:-9999px;opacity:0;';\n      document.body.appendChild(ta);\n      ta.focus(); ta.select();\n      document.execCommand('copy');\n      document.body.removeChild(ta);\n      btn.classList.add('copied');\n      lbl.textContent = 'Copied!';\n      setTimeout(function(){ btn.classList.remove('copied'); lbl.textContent = 'Copy agent prompt'; }, 2200);\n    } catch(e) {\n      lbl.textContent = 'Failed';\n      setTimeout(function(){ lbl.textContent = 'Copy agent prompt'; }, 2000);\n    }\n  });\n})();\n<\/script>","protected":false},"excerpt":{"rendered":"<p>D DPS.MEDIA WP \u63d2\u4ef6\u5f00\u53d1\u6307\u5357 \u2014 \u5185\u90e8\u526f\u672c \u590d\u5236 agent \u63d0\u793a\u8bcd H Hi\u1ec3n CEO \u00b7 DPS.MEDIA WordPressPlugin DevGuide \u56e2\u961f\u7684 flow \u6e90\u7801 \u2192 \u6784\u5efa \u2192 \u53d1\u5e03\u3002\u8db3\u4ee5\u8fdb\u884c\u672c\u5730\u5f00\u53d1\u3001\u6253\u5305 ZIP \u5e76\u5b89\u88c5\u5230 WordPress \u751f\u4ea7\u73af\u5883\u3002 PHP 8.x WordPress hooks API @wordpress\/scripts React (Admin UI) Webpack 5 npm scripts Node.js \u2265 18 ZIP \u53d1\u5e03 \u7ed3\u6784 [\u2026]<\/p>","protected":false},"author":1,"featured_media":37957,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,1204],"tags":[],"class_list":["post-37956","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","category-wordpress-marketing"],"acf":[],"rankmath_keywords":{"primary":"","secondary":[""]},"yoast_keywords":{"primary":"","secondary":[]},"yoast_focuskw":"","rankmath_focuskw":"","seo_keywords":{"primary":"","secondary":[""]},"_links":{"self":[{"href":"https:\/\/dps.media\/zh\/wp-json\/wp\/v2\/posts\/37956","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dps.media\/zh\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dps.media\/zh\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dps.media\/zh\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dps.media\/zh\/wp-json\/wp\/v2\/comments?post=37956"}],"version-history":[{"count":0,"href":"https:\/\/dps.media\/zh\/wp-json\/wp\/v2\/posts\/37956\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dps.media\/zh\/wp-json\/wp\/v2\/media\/37957"}],"wp:attachment":[{"href":"https:\/\/dps.media\/zh\/wp-json\/wp\/v2\/media?parent=37956"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dps.media\/zh\/wp-json\/wp\/v2\/categories?post=37956"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dps.media\/zh\/wp-json\/wp\/v2\/tags?post=37956"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}