You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails升级Shakapacker时CoffeeScript报'reserved word var'错误

问题

将使用Webpacker 5的遗留Rails应用升级到Shakapacker v6.0.0.rc.6(Webpacker已退役2年),按官方指引修改Webpacker配置后,执行rake assets:precompile时CoffeeScript文件编译失败,报错:CoffeeScriptError: reserved word 'var'。已尝试更换多个coffee-script版本、简化测试文件,问题仍未解决,附上相关配置及规则输出。

相关配置

config/webpack/environment.js

const { webpackConfig } = require('@rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')
const vue =  require('./loaders/vue')
const coffee = require('./loaders/coffee')
const sass = require('./loaders/sass.js')
const yaml = require('./loaders/yaml.js')
const pug = require('./loaders/pug.js')
const webpack = require('webpack');

webpackConfig.plugins = [
    ...webpackConfig.plugins,
    new VueLoaderPlugin(),
    new webpack.DefinePlugin({
        __VUE_OPTIONS_API__: true,
        __VUE_PROD_DEVTOOLS__: false,
    })
]

webpackConfig.module.rules = [
    vue,
    ...webpackConfig.module.rules,
    pug,
    coffee,
    sass,
    yaml
]

delete webpackConfig.module.rules['nodeModules']

const scssConfigIndex = webpackConfig.module.rules.findIndex((config) => ".scss".match(config.test))
webpackConfig.module.rules.splice(scssConfigIndex, 1)

webpackConfig.resolve = {
  extensions: [".coffee", ".vue", ".mjs", ".js", ".sass", ".scss", ".css", ".module.sass",
    ".module.scss", ".module.css", ".png", ".svg", ".gif", ".jpeg", ".jpg"]
}

module.exports = webpackConfig

config/webpack/loaders/coffee.js

module.exports = {
  test: /\.coffee$/,
  use: ["babel-loader", "coffee-loader"]
}

app/javascript/packs/test.coffee

hello = -> console.log('Hi!')

规则输出

[
  { test: /\.vue(\.erb)?$/, use: [ [Object] ] },
  {
    test: [ /\.html$/ ],
    exclude: [ /\.(js|mjs|jsx|ts|tsx)$/ ],
    type: 'asset/source'
  },
  {
    test: [
      /\.bmp$/,   /\.gif$/,
      /\.jpe?g$/, /\.png$/,
      /\.tiff$/,  /\.ico$/,
      /\.avif$/,  /\.webp$/,
      /\.eot$/,   /\.otf$/,
      /\.ttf$/,   /\.woff$/,
      /\.woff2$/, /\.svg$/
    ],
    exclude: [ /\.(js|mjs|jsx|ts|tsx)$/ ],
    type: 'asset/resource',
    generator: { filename: 'static/[name]-[hash][ext][query]' }
  },
  {
    test: /\.(css)$/i,
    use: [
      '/Users/long.luongngoc/Documents/projects/cgi/mmog-le/node_modules/mini-css-extract-plugin/dist/loader.js',
      [Object]
    ]
  },
  {
    test: /\.(js|jsx|mjs|ts|tsx|coffee)?(\.erb)?$/,
    include: [
      '/Users/long.luongngoc/Documents/projects/cgi/mmog-le/app/javascript'
    ],
    exclude: /node_modules/,
    use: [ [Object] ]
  },
  { test: /\.coffee(\.erb)?$/, use: [ [Object] ] },
  { test: /\.pug$/, use: [ [Object] ] },
  { test: /\.coffee$/, use: [ 'babel-loader', 'coffee-loader' ] },
  {
    test: /\.sass$/,
    use: [
      'vue-style-loader',
      'css-loader',
      'resolve-url-loader',
      [Object]
    ]
  },
  { test: /\.ya?ml$/, use: [ 'yaml-js-loader' ] }
]
解决方案

问题根源

从规则输出能看到,多个loader规则同时匹配了.coffee文件:

  1. 内置JS规则test: /\.(js|jsx|mjs|ts|tsx|coffee)?(\.erb)?$/会优先处理coffee文件,但babel-loader无法识别CoffeeScript语法,直接将其当作JS解析,生成了包含var的代码;随后coffee-loader再处理这些已被错误解析的代码,就会抛出reserved word 'var'错误。
  2. 自定义的coffee规则虽然存在,但因为webpack规则按顺序匹配,前面的内置规则已经先处理了文件,导致自定义规则要么执行顺序不对,要么重复处理。

修复步骤

  1. 调整规则顺序,让coffee-loader优先匹配
    修改environment.js中的规则数组,把自定义coffee规则移到内置规则之前:

    webpackConfig.module.rules = [
        vue,
        coffee, // 优先匹配coffee文件
        ...webpackConfig.module.rules,
        pug,
        sass,
        yaml
    ]
    
  2. 排除内置JS规则对coffee文件的处理
    在environment.js中找到内置JS规则,添加排除逻辑,避免它处理coffee文件:

    const jsRuleIndex = webpackConfig.module.rules.findIndex(rule => 
        rule.test && rule.test.toString().includes('coffee')
    );
    if (jsRuleIndex !== -1) {
        webpackConfig.module.rules[jsRuleIndex].exclude = [
            ...(webpackConfig.module.rules[jsRuleIndex].exclude || []),
            /\.coffee$/
        ];
    }
    
  3. 确保依赖版本兼容
    Shakapacker v6建议搭配coffee-loader@4.x和coffee-script@2.x,执行以下命令安装适配版本:

    npm install coffee-loader@4 coffee-script@2 --save-dev
    
  4. 统一coffee规则的匹配范围
    规则输出中存在一条{ test: /\.coffee(\.erb)?$/, use: [ [Object] ] }的内置规则,可将自定义coffee规则的匹配范围扩展到.coffee.erb,避免重复规则冲突:
    修改config/webpack/loaders/coffee.js:

    module.exports = {
      test: /\.coffee(\.erb)?$/,
      use: ["babel-loader", "coffee-loader"]
    }
    

内容的提问来源于stack exchange,提问作者Long Luong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 02:17:05