I am using @rails/webpacker of version 5.4.3 with webpacker gems of version '~> 5.0'. Previously I was using webpacker 4 and it was working. However, switching to webpacker 5 is creating multiple issues and not sure if it's due to extract_css. If extract_css is false in webpacker.yml I get below issue where it says "Failed to mount component: template or render function not defined"
This is how I have my webpack setup
config/webpack/loaders/vue.js
const { dev_server: devServer } = require('@rails/webpacker').config;
const isProduction = process.env.NODE_ENV === 'production';
const inDevServer = process.argv.find((v) => v.includes('webpack-dev-server'));
const extractCSS = !(inDevServer && devServer && devServer.hmr) || isProduction;
module.exports = {
test: /\.vue(\.erb)?$/,
use: [
{
loader: 'vue-loader',
options: { extractCSS, compilerOptions: { whitespace: 'condense' } },
},
],
};
webpacker.yml
default: &default
public_root_path: public
check_yarn_integrity: false
source_path: app/javascript
source_entry_path: packs
public_output_path: packs
cache_path: tmp/cache/webpacker
extract_css: false
webpack_compile_output: true
# Additional paths webpack should lookup modules
# ['app/assets', 'engine/foo/app/assets']
resolved_paths: []
# Reload manifest.json on all requests so we reload latest compiled packs
cache_manifest: false
static_assets_extensions:
- .jpg
- .jpeg
- .png
- .gif
- .tiff
- .ico
- .svg
- .eot
- .otf
- .ttf
- .woff
- .woff2
extensions:
- .vue
- .js
- .sass
- .scss
- .css
- .png
- .svg
- .gif
- .jpeg
- .jpg
development:
<<: *default
compile: true
# Reference: https://webpack.js.org/configuration/dev-server/
dev_server:
https: false
host: localhost
port: 3035
public: localhost:3035
hmr: true
# Inline should be set to true if using HMR
inline: true
overlay: true
compress: true
disable_host_check: true
use_local_ip: false
quiet: false
pretty: false
headers:
"Access-Control-Allow-Origin": "*"
watch_options:
ignored: "**/node_modules/**"
test:
<<: *default
compile: true
# Compile test packs to a separate directory
public_output_path: packs-test
staging:
<<: *default
# Production depends on precompilation of packs prior to booting for performance.
compile: false
# Cache manifest.json for performance
cache_manifest: true
webpack_compile_output: false
production:
<<: *default
# Production depends on precompilation of packs prior to booting for performance.
compile: false
# Cache manifest.json for performance
cache_manifest: true
# Extract and emit a css file
extract_css: true
webpack_compile_output: false
config/webpack/environment.js
const { environment } = require('@rails/webpacker');
const vue = require('./loaders/vue');
const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const TerserPlugin = require('terser-webpack-plugin');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// const { sass } = require('@rails/webpacker/package/rules');
const isEnvProduction = environment.config.mode === 'production';
const isEnvDevelopment = environment.config.mode === 'development';
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const customConfig = {
resolve: {
fallback: {
dgram: false,
fs: false,
net: false,
tls: false,
child_process: false,
},
},
entry: {
vendor: ['babel-polyfill', 'vue', 'moment', 'axios'],
},
};
const getStyleLoaders = (cssOptions) => {
const loaders = [
isEnvDevelopment && require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: cssOptions,
},
].filter(Boolean);
return loaders;
};
const customCssLoaderOptions = {
localIdentName: '[name]__[local]--[hash:base64:5]',
// minimize: environment.NODE_ENV === 'production',
modules: true,
};
environment.splitChunks((config) => {
return {
...config,
...{
optimization: {
splitChunks: { chunks: 'all', name: '~' },
runtimeChunk: true,
},
},
};
});
environment.config.delete('node.dgram');
environment.config.delete('node.fs');
environment.config.delete('node.net');
environment.config.delete('node.tls');
environment.config.delete('node.child_process');
environment.loaders.delete('css');
environment.config.merge(customConfig);
environment.plugins.append('VueLoaderPlugin', new VueLoaderPlugin());
environment.loaders.append('vue', {
test: /\.vue$/,
loader: 'vue-loader',
});
// Comment this if you need case-sensitive-paths-plugin in local development.
if (process.env.RAILS_ENV === 'development') {
environment.plugins.delete('CaseSensitivePaths');
// Only add en.js locale for local development.
environment.plugins.append('moment', new webpack.ContextReplacementPlugin(/moment[/\\]locale/, /(en).js/));
}
environment.plugins.prepend('Environment', new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(process.env))));
environment.plugins.prepend(
'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
jquery: 'jquery',
})
);
const config = environment.toWebpackConfig();
config.resolve.alias = {
jquery: 'jquery/src/jquery',
};
let sassLoader = environment.loaders.get('sass').use.find((item) => item.loader === 'sass-loader');
sassLoader = {
...sassLoader,
options: {
...sassLoader.options,
sassOptions: {
...sassLoader.options.sassOptions,
includePaths: ['./node_modules'],
},
},
};
// const CSSLoader = environment.loaders.get('sass').use.find(el => el.loader === 'css-loader')
// CSSLoader.options = {...CSSLoader.options, customCssLoaderOptions}
// let miniCssExtractPlugin = environment.plugins.get('MiniCssExtract');
// console.log('miniCssExtractPlugin', miniCssExtractPlugin)
environment.loaders.append('vue', vue);
environment.config.merge({
optimization: {
minimize: false, // should be isProduction
minimizer: [
new TerserPlugin({
test: /\.js(\?.*)?$/i,
}),
],
},
resolve: {
alias: {
app: path.resolve(__dirname, '../../app/'),
},
},
module: {
rules: [
{
oneOf: [
{
test: cssRegex,
exclude: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: false,
modules: {
mode: 'icss',
},
}),
sideEffects: true,
},
],
},
].filter(Boolean),
},
});
module.exports = environment;
If I turn extract_css to true in default section and recompile I get this issue
Webpacker can't find construction_project_home_module.css in 'public/packs/manifest.json. Possible causes:'
- You want to set webpacker.yml value of compile to true for your environment unless you are using the
webpack -wor the webpack-dev-server.- webpack has not yet re-run to reflect updates.
- You have misconfigured Webpacker's config/webpacker.yml file.
- Your webpack configuration is not creating a manifest.
I am not sure what's causing such issue and what's the recommended approach for handling extract_css. Could anyone please check my webpack config and help me solve my issue? Since extract_css gave multiple type of issue so I presented both of them so that it will be easier for the one who wants to help me solve this issue.
These are the version of the package used;
webpacker ~> 5.0 @rails/webpacker 5.4.3 webpack 5.4.3 webpack-dev-server 4.9.0 vue 2.5.13 rails 5.2.7