Rails 6技术咨询:自定义JS放置位置与样式表目录合理性
Why Put Stylesheets in app/javascript/stylesheets?
Rails 6 switched to Webpacker as its default JavaScript bundler, which fundamentally changes how assets are handled compared to the older Asset Pipeline. Here’s the breakdown of this choice:
- Webpack is a module bundler, not just a JS or CSS processor. It treats all assets (JS, CSS, images, fonts) as interconnected modules. When you import a CSS/SCSS file into your JavaScript entry point (like
application.js), Webpack processes it alongside your JS—handling minification, autoprefixing, dependency tracking, and code splitting—then bundles everything into optimized files for production. - This structure aligns with modern frontend practices where component-specific styles live close to their corresponding JS components. Even for global styles (like the tutorial’s setup), keeping them under
app/javascriptlets Webpack manage them as part of the same build pipeline, avoiding separate tooling for CSS. - Rails doesn’t include this structure out of the box because Webpacker is designed to be flexible. Unlike the Asset Pipeline’s rigid
assets/stylesheets/assets/javascriptssplit, Webpack encourages you to organize files in a way that makes sense for your project. The tutorial’s setup is just a common convention to centralize global styles while leveraging Webpack’s capabilities.
Alternative Places for Custom JavaScript (Non-Library Files)
You don’t have to cram all your custom JS into the default app/javascript/packs directory (which is meant for entry point files like application.js). Here are clean, maintainable options:
1. Create Dedicated Subdirectories Under app/javascript
Organize your code by purpose or feature to keep things tidy:
app/javascript/components: For reusable UI components (e.g.,navbar.js,modal.js)app/javascript/utils: For helper functions (e.g.,date-formatter.js,api-client.js)app/javascript/custom: For project-specific, one-off scripts (e.g.,dashboard-interactions.js,form-validators.js)
To use these files, simply import them into your entry point (or another module):
// In app/javascript/packs/application.js import '../components/navbar'; import '../utils/api-client';
2. Use Webpack Aliases for Cleaner Imports
If you want to avoid messy relative paths, set up aliases in your Webpack config:
- Open
config/webpack/environment.js - Add the following (adjust paths as needed):
const { environment } = require('@rails/webpacker'); const path = require('path'); environment.config.set('resolve.alias', { '@components': path.resolve(__dirname, '../../app/javascript/components'), '@utils': path.resolve(__dirname, '../../app/javascript/utils') }); module.exports = environment;
Now you can import files with concise paths:
import Navbar from '@components/navbar'; import { formatDate } from '@utils/date-formatter';
3. Fall Back to the Asset Pipeline (Not Recommended)
If you really prefer the old structure, you can still use app/assets/javascripts for custom JS:
- Add your files to
app/assets/javascripts - Update
config/initializers/assets.rbto include the directory (if needed):
Rails.application.config.assets.paths << Rails.root.join('app', 'assets', 'javascripts')
- Include them in your layout with
javascript_include_tag:
<%= javascript_include_tag 'custom-script', 'data-turbo-track': 'reload' %>
Note: This bypasses Webpack, so you’ll miss out on benefits like tree shaking, module bundling, and modern JS transpilation. It’s better to embrace Webpack for long-term maintainability.
内容的提问来源于stack exchange,提问作者Rajan Verma

