Rails 7迁移时Webpack 5配置问题:SCSS需与JS同目录才可编译
Rails 7 + Webpacker 5 分离SCSS与JS文件编译问题解决方案
问题概述
迁移项目至Rails 7并搭配Webpacker 5、Bootstrap时,遇到Webpack仅编译与JS同目录(javascript/packs)的SCSS文件的问题,希望保持SCSS与JS文件结构分离(保留现有app/assets/stylesheets结构或迁移至app/javascript/stylesheets)。
当前项目结构:
- app - assets - stylesheets - application.scss - admin.scss - sessions.scss - javascript - packs - application.js - admin.js - config - webpack - webpack.config.js
解决方案
1. 修正Entry入口路径
当前webpack.config.js的entry配置指向了不存在的javascript/packs/stylesheets目录,需改为指向实际的SCSS文件位置。由于配置文件位于config/webpack,需使用正确的相对路径:
entry: { application: [ './packs/application.js', '../../assets/stylesheets/application.scss' ], admin: [ './packs/admin.js', '../../assets/stylesheets/admin.scss' ], sessions: [ '../../assets/stylesheets/sessions.scss' ], },
2. 配置Webpack模块解析路径
添加resolve.modules,让Webpack能够直接识别app/assets目录下的文件,避免冗长的相对路径:
resolve: { modules: [path.resolve(__dirname, '../../app/assets'), 'node_modules'], alias: { jquery: 'jquery/src/jquery', jquery_ui: 'jquery-ui-dist/jquery-ui.js' } },
配置后,entry可简化为:
entry: { application: [ './packs/application.js', 'stylesheets/application.scss' ], admin: [ './packs/admin.js', 'stylesheets/admin.scss' ], sessions: [ 'stylesheets/sessions.scss' ], },
3. 确保CSS提取插件正确配置
Webpacker默认集成了CSS处理,但自定义配置需显式添加MiniCssExtractPlugin以将SCSS编译为独立CSS文件(而非打包进JS):
plugins: [ new MiniCssExtractPlugin({ filename: 'css/[name][contenthash].css' }) ],
4. 调整Output路径与Webpacker默认对齐
将output路径改为Webpacker默认的public/packs,避免文件输出混乱:
output: { path: path.resolve(__dirname, '../../public/packs'), filename: 'js/[name][contenthash].js', clean: true, assetModuleFilename: 'media/[name][ext]' },
5. 可选:迁移至app/javascript/stylesheets结构
若更倾向于遵循Webpacker的约定,可将SCSS文件移至app/javascript/stylesheets,此时entry路径可简化为:
entry: { application: [ './packs/application.js', './stylesheets/application.scss' ], admin: [ './packs/admin.js', './stylesheets/admin.scss' ], sessions: [ './stylesheets/sessions.scss' ], },
完整修改后的webpack.config.js
const { webpackConfig, merge } = require('@rails/webpacker') const MiniCssExtractPlugin = require('mini-css-extract-plugin') const path = require('path') const customConfig = { mode: 'development', entry: { application: [ './packs/application.js', '../../assets/stylesheets/application.scss' ], admin: [ './packs/admin.js', '../../assets/stylesheets/admin.scss' ], sessions: [ '../../assets/stylesheets/sessions.scss' ], }, output: { path: path.resolve(__dirname, '../../public/packs'), filename: 'js/[name][contenthash].js', clean: true, assetModuleFilename: 'media/[name][ext]' }, module: { rules: [ { test: /\.scss$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader' ], exclude: /node_modules/ }, ] }, resolve: { modules: [path.resolve(__dirname, '../../app/assets'), 'node_modules'], alias: { jquery: 'jquery/src/jquery', jquery_ui: 'jquery-ui-dist/jquery-ui.js' } }, plugins: [ new MiniCssExtractPlugin({ filename: 'css/[name][contenthash].css' }) ] } module.exports = merge(webpackConfig, customConfig)
验证与引用
编译后,CSS文件会输出至public/packs/css目录,在Rails视图中使用stylesheet_pack_tag引用:
<%= stylesheet_pack_tag 'application' %> <%= stylesheet_pack_tag 'admin' %> <%= stylesheet_pack_tag 'sessions' %>
内容的提问来源于stack exchange,提问作者Grazi
相关产品推荐
相关产品推荐

