webpacker 5 complains "Failed to mount component: template or render function not defined"

Viewed 64

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"enter image description here

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:'

  1. You want to set webpacker.yml value of compile to true for your environment unless you are using the webpack -w or the webpack-dev-server.
  2. webpack has not yet re-run to reflect updates.
  3. You have misconfigured Webpacker's config/webpacker.yml file.
  4. 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

0 Answers
Related