开发工具推荐
本指南推荐一系列工具和资源,帮助您提升 Shopify 主题开发的效率和质量。
代码编辑器
1. Visual Studio Code (推荐)
安装和配置
VS Code 是最受欢迎的 Shopify 主题开发编辑器,提供丰富的插件支持。
必备插件:
// .vscode/extensions.json
{
  "recommendations": [
    "shopify.liquid",
    "shopify.theme-check-vscode",
    "bradlc.vscode-tailwindcss",
    "esbenp.prettier-vscode",
    "ms-vscode.vscode-json",
    "formulahendry.auto-rename-tag",
    "christian-kohler.path-intellisense",
    "ms-vscode.vscode-css-formatter",
    "zignd.html-css-class-completion"
  ]
}工作区配置:
// .vscode/settings.json
{
  "liquid.format.enable": true,
  "liquid.completion.enable": true,
  "liquid.hover.enable": true,
  "files.associations": {
    "*.liquid": "liquid"
  },
  "emmet.includeLanguages": {
    "liquid": "html"
  },
  "editor.quickSuggestions": {
    "strings": true
  },
  "editor.formatOnSave": true,
  "prettier.documentSelectors": ["**/*.liquid"],
  "css.validate": false,
  "scss.validate": false
}代码片段配置:
// .vscode/liquid.code-snippets
{
  "Liquid Comment Block": {
    "prefix": "comment",
    "body": [
      "{% comment %}",
      "  $1",
      "{% endcomment %}"
    ],
    "description": "Create a Liquid comment block"
  },
  
  "Product Card": {
    "prefix": "product-card",
    "body": [
      "<div class=\"product-card\">",
      "  <a href=\"{{ product.url }}\">",
      "    <img src=\"{{ product.featured_image | img_url: '300x300' }}\" alt=\"{{ product.title }}\">",
      "    <h3>{{ product.title }}</h3>",
      "    <p>{{ product.price | money }}</p>",
      "  </a>",
      "</div>"
    ]
  },
  
  "For Loop with Liquid": {
    "prefix": "for-liquid",
    "body": [
      "{%- liquid",
      "  for $1 in $2",
      "    $3",
      "  endfor",
      "-%}"
    ]
  },
  
  "Section Schema": {
    "prefix": "schema",
    "body": [
      "{% schema %}",
      "{",
      "  \"name\": \"$1\",",
      "  \"settings\": [",
      "    {",
      "      \"type\": \"text\",",
      "      \"id\": \"$2\",",
      "      \"label\": \"$3\"",
      "    }",
      "  ]",
      "}",
      "{% endschema %}"
    ]
  }
}2. Sublime Text
包管理器配置:
// Package Control.sublime-settings
{
  "installed_packages": [
    "Liquid",
    "Shopify Liquid",
    "Emmet",
    "SideBarEnhancements",
    "BracketHighlighter",
    "GitGutter"
  ]
}3. Atom (已停止维护)
虽然 Atom 已停止维护,但仍有一些有用的包:
language-liquidshopify-liquidemmet
命令行工具
1. Shopify CLI
安装:
# 使用 Homebrew (macOS)
brew tap shopify/shopify
brew install shopify-cli
 
# 使用 npm
npm install -g @shopify/cli @shopify/theme
 
# 使用 Ruby Gem
gem install shopify-cli常用命令:
# 登录 Shopify
shopify auth login
 
# 初始化新主题
shopify theme init my-theme
 
# 开发模式 (实时同步)
shopify theme dev
 
# 推送到主题
shopify theme push
 
# 拉取主题
shopify theme pull
 
# 查看主题列表
shopify theme list
 
# 预览主题
shopify theme open
 
# 发布主题
shopify theme publish
 
# 检查主题
shopify theme check配置文件:
# shopify.theme.toml
[environments.development]
store = "your-dev-store.myshopify.com"
theme = "development"
 
[environments.staging]
store = "your-staging-store.myshopify.com"
theme = "staging"
 
[environments.production]
store = "your-store.myshopify.com"
theme = "live"2. Theme Check
安装和使用:
# 安装
npm install -g @shopify/theme-check
 
# 检查当前目录
theme-check
 
# 检查特定文件
theme-check templates/product.liquid
 
# 自动修复
theme-check --auto-correct配置文件:
# .theme-check.yml
extends: :theme_app_extension
 
ChecksumAssetBundles:
  enabled: false
 
AssetSizeCSS:
  threshold_in_bytes: 100000
 
AssetSizeJavaScript:
  threshold_in_bytes: 150000
 
DeprecatedLazysizes:
  enabled: true
 
RemoteAsset:
  enabled: true3. Lighthouse CI
性能检测配置:
// lighthouserc.json
{
  "ci": {
    "collect": {
      "url": [
        "https://your-store.myshopify.com",
        "https://your-store.myshopify.com/products/example",
        "https://your-store.myshopify.com/collections/all"
      ],
      "numberOfRuns": 3
    },
    "assert": {
      "assertions": {
        "categories:performance": ["error", {"minScore": 0.8}],
        "categories:accessibility": ["error", {"minScore": 0.9}],
        "categories:best-practices": ["error", {"minScore": 0.9}],
        "categories:seo": ["error", {"minScore": 0.9}]
      }
    }
  }
}构建工具
1. Webpack 配置
基础配置:
// webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
 
module.exports = {
  entry: {
    main: './src/js/main.js',
    product: './src/js/product.js',
    cart: './src/js/cart.js'
  },
  
  output: {
    path: path.resolve(__dirname, 'assets'),
    filename: '[name].bundle.js',
    clean: true
  },
  
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      },
      
      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader'
        ]
      },
      
      {
        test: /\.(png|jpg|gif|svg)$/,
        type: 'asset/resource',
        generator: {
          filename: 'images/[name][ext]'
        }
      }
    ]
  },
  
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].css'
    })
  ],
  
  optimization: {
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true
          }
        }
      })
    ]
  },
  
  devtool: 'source-map'
};2. Vite 配置
// vite.config.js
import { defineConfig } from 'vite';
import { resolve } from 'path';
 
export default defineConfig({
  build: {
    outDir: 'assets',
    rollupOptions: {
      input: {
        main: resolve(__dirname, 'src/js/main.js'),
        product: resolve(__dirname, 'src/js/product.js'),
        cart: resolve(__dirname, 'src/js/cart.js')
      },
      output: {
        entryFileNames: '[name].js',
        chunkFileNames: '[name].js',
        assetFileNames: '[name].[ext]'
      }
    }
  },
  
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@import "@/styles/variables.scss";`
      }
    }
  }
});3. PostCSS 配置
// postcss.config.js
module.exports = {
  plugins: [
    require('tailwindcss'),
    require('autoprefixer'),
    require('cssnano')({
      preset: 'default'
    })
  ]
};测试工具
1. Jest 配置
// jest.config.js
module.exports = {
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['<rootDir>/tests/setup.js'],
  testMatch: [
    '<rootDir>/tests/**/*.test.js'
  ],
  collectCoverageFrom: [
    'assets/js/**/*.js',
    '!assets/js/vendor/**'
  ],
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80
    }
  }
};测试示例:
// tests/cart.test.js
import { CartManager } from '../assets/js/cart.js';
 
describe('CartManager', () => {
  let cart;
  
  beforeEach(() => {
    document.body.innerHTML = `
      <div data-cart-drawer></div>
      <span data-cart-count>0</span>
    `;
    
    cart = new CartManager();
  });
  
  test('should initialize with empty cart', () => {
    expect(cart.itemCount).toBe(0);
  });
  
  test('should add item to cart', async () => {
    const mockResponse = {
      item_count: 1,
      items: [{ id: 123, quantity: 1 }]
    };
    
    global.fetch = jest.fn().mockResolvedValue({
      ok: true,
      json: () => Promise.resolve(mockResponse)
    });
    
    await cart.addItem(123, 1);
    
    expect(cart.itemCount).toBe(1);
  });
});2. Playwright E2E 测试
// tests/e2e/product.spec.js
const { test, expect } = require('@playwright/test');
 
test.describe('Product Page', () => {
  test('should add product to cart', async ({ page }) => {
    await page.goto('/products/example-product');
    
    // 选择变体
    await page.selectOption('[data-variant-select]', '123456');
    
    // 添加到购物车
    await page.click('[data-add-to-cart]');
    
    // 验证购物车更新
    await expect(page.locator('[data-cart-count]')).toHaveText('1');
    
    // 验证购物车抽屉打开
    await expect(page.locator('[data-cart-drawer]')).toBeVisible();
  });
  
  test('should show correct product information', async ({ page }) => {
    await page.goto('/products/example-product');
    
    await expect(page.locator('h1')).toContainText('Example Product');
    await expect(page.locator('[data-price]')).toBeVisible();
    await expect(page.locator('[data-product-image]')).toBeVisible();
  });
});性能监控工具
1. Web Vitals 监控
// assets/js/performance.js
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
 
function sendToAnalytics(metric) {
  const body = JSON.stringify(metric);
  
  // 使用 navigator.sendBeacon() 发送数据
  if (navigator.sendBeacon) {
    navigator.sendBeacon('/api/vitals', body);
  } else {
    fetch('/api/vitals', { body, method: 'POST', keepalive: true });
  }
}
 
// 监控所有 Web Vitals
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getFCP(sendToAnalytics);
getLCP(sendToAnalytics);
getTTFB(sendToAnalytics);2. Bundle 分析
// webpack-bundle-analyzer.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 
module.exports = {
  // ... 其他配置
  plugins: [
    new BundleAnalyzerPlugin({
      analyzerMode: 'static',
      openAnalyzer: false,
      reportFilename: 'bundle-report.html'
    })
  ]
};部署和CI/CD
1. GitHub Actions
# .github/workflows/deploy.yml
name: Deploy to Shopify
 
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
 
jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run tests
      run: npm test
    
    - name: Run theme check
      run: npx @shopify/theme-check
    
    - name: Build assets
      run: npm run build
 
  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Shopify CLI
      uses: shopify/github-action@v1
      with:
        shopify_cli_version: latest
    
    - name: Deploy to staging
      run: shopify theme push --environment staging
      env:
        SHOPIFY_CLI_TOKEN: ${{ secrets.SHOPIFY_CLI_TOKEN }}
    
    - name: Run E2E tests
      run: npx playwright test
      env:
        STORE_URL: ${{ secrets.STAGING_STORE_URL }}
    
    - name: Deploy to production
      if: success()
      run: shopify theme push --environment production
      env:
        SHOPIFY_CLI_TOKEN: ${{ secrets.SHOPIFY_CLI_TOKEN }}2. 自动化脚本
// scripts/deploy.js
const { execSync } = require('child_process');
const readline = require('readline');
 
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});
 
async function deploy() {
  console.log('🚀 开始部署流程...');
  
  // 1. 运行测试
  console.log('📋 运行测试...');
  execSync('npm test', { stdio: 'inherit' });
  
  // 2. 检查主题
  console.log('🔍 检查主题...');
  execSync('npx @shopify/theme-check', { stdio: 'inherit' });
  
  // 3. 构建资源
  console.log('🏗️ 构建资源...');
  execSync('npm run build', { stdio: 'inherit' });
  
  // 4. 确认部署
  const answer = await new Promise(resolve => {
    rl.question('📤 是否部署到生产环境? (y/N): ', resolve);
  });
  
  if (answer.toLowerCase() === 'y') {
    console.log('🚀 部署到生产环境...');
    execSync('shopify theme push --environment production', { stdio: 'inherit' });
    console.log('✅ 部署完成!');
  } else {
    console.log('❌ 部署已取消');
  }
  
  rl.close();
}
 
deploy().catch(console.error);调试工具
1. Chrome DevTools 扩展
Shopify DevTools:
- 检查 Liquid 变量
 - 监控 AJAX 请求
 - 分析性能
 
React Developer Tools:
- 如果使用 React 组件
 
2. 浏览器书签工具
// Shopify Debug 书签
javascript:(function(){
  const debugInfo = {
    theme: window.Shopify?.theme,
    shop: window.Shopify?.shop,
    customer: window.Shopify?.customer,
    cart: window.Shopify?.cart,
    product: window.product,
    collection: window.collection
  };
  
  console.group('🛍️ Shopify Debug Info');
  Object.entries(debugInfo).forEach(([key, value]) => {
    if (value) {
      console.log(`${key}:`, value);
    }
  });
  console.groupEnd();
  
  // 显示所有 Liquid 变量
  const scripts = document.querySelectorAll('script[type="application/json"]');
  scripts.forEach(script => {
    try {
      const data = JSON.parse(script.textContent);
      console.log(`📄 ${script.id || 'JSON Data'}:`, data);
    } catch (e) {
      // 忽略无效 JSON
    }
  });
})();3. 本地开发代理
// proxy-server.js
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
 
const app = express();
 
// 代理到 Shopify 店铺
const proxy = createProxyMiddleware({
  target: 'https://your-store.myshopify.com',
  changeOrigin: true,
  onProxyReq: (proxyReq, req, res) => {
    // 添加调试头
    proxyReq.setHeader('X-Debug-Mode', 'true');
  },
  onProxyRes: (proxyRes, req, res) => {
    // 注入调试脚本
    if (proxyRes.headers['content-type']?.includes('text/html')) {
      // 修改响应内容
    }
  }
});
 
app.use('/', proxy);
 
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`🔗 代理服务器运行在 http://localhost:${PORT}`);
});文档生成工具
1. JSDoc 配置
// jsdoc.config.json
{
  "source": {
    "include": ["./assets/js/"],
    "includePattern": "\\.(js)$",
    "exclude": ["node_modules/"]
  },
  "opts": {
    "destination": "./docs/js/"
  },
  "plugins": ["plugins/markdown"]
}2. Storybook 配置
// .storybook/main.js
module.exports = {
  stories: ['../stories/**/*.stories.@(js|jsx|ts|tsx)'],
  addons: [
    '@storybook/addon-essentials',
    '@storybook/addon-a11y',
    '@storybook/addon-viewport'
  ]
};通过这些工具的配合使用,您可以建立一个高效、专业的 Shopify 主题开发工作流程!
下一步学习
掌握开发工具后,建议继续学习:
最后更新时间: