Maronato / vue-toastification

Vue notifications made easy!
https://vue-toastification.maronato.dev
MIT License
3.11k stars 140 forks source link

Vue-toastification does not show toasts with vue 3 #354

Open netandreus opened 1 year ago

netandreus commented 1 year ago

Versions

Describe the bug

I just installed this package like this:

main.ts

import { createApp } from "vue"
import App from "./components/App.vue"
import Toast, { PluginOptions } from "vue-toastification";
import "vue-toastification/dist/index.css";

const app = createApp(App);
const options: PluginOptions = {
    // You can set your default options here
};
app.use(Toast, options);
...
app.mount("#vue-app");

I use Pinia for state management. Somewhere in

./stores/AuthStore.ts

import { useToast } from "vue-toastification";
...
export const useAuthStore = defineStore({
...
     async onLoginButtonClick() {
           let url: string = '/api/user/auth'
           let toastr = useToast();
            ...
            toastr.success("You are logged in");
            ...
});

There is no toast shows at the page. In browser console there is this error:

[Vue warn]: Property "positions" was accessed during render but is not defined on instance.

Expected behavior

Toast is visible at the page.

Steps to reproduce

Install with this config files.

packages.json

{
...
    "devDependencies": {
        "@babel/core": "^7.19.6",
        "@babel/preset-env": "^7.19.0",
        "@popperjs/core": "^2.11.6",
        "autoprefixer": "^10.4.8",
        "babel-loader": "^9.0.1",
        "bootstrap": "^5.2.2",
        "@types/bootstrap": "5.1.9",
        "copy-webpack-plugin": "^11.0.0",
        "css-loader": "^6.7.1",
        "dotenv-webpack": "^8.0.1",
        "fast-glob": "^3.2.12",
        "mime-types": "^2.1.34",
        "mini-css-extract-plugin": "^2.6.1",
        "path": "^0.12.7",
        "postcss": "^8.4.12",
        "postcss-loader": "^7.0.1",
        "postcss-preset-env": "^7.8.1",
        "sass": "^1.54.9",
        "sass-loader": "^13.0.2",
        "sharp": "^0.31.0",
        "style-loader": "^3.3.1",
        "trash": "^8.1.0",
        "uuid": "^9.0.0",
        "webpack": "^5.74.0",
        "webpack-cli": "4.10.0",
        "typescript": "^4.8.4",
        "ts-loader": "^9.4.1",
        "@types/node": "18.11.9",
        "source-map-loader": "^4.0.1",
        "vue": "^3.2.41",
        "vue-loader": "^17.0.1",
        "@vue/compiler-sfc": "^3.2.41",
        "pinia": "^2.0.23",
        "vue-router": "^4.1.6",
        "vue-style-loader": "4.1.3",
        "rsdi": "2.2.2",
        "emoji-button": "file:../shared/emoji-button/",
        "autosize": "^5.0.1",
        "dropzone": "^5.9.3",
        "zoom-vanilla.js": "^2.0.6",
        "@types/autosize": "4.0.1",
        "@types/dropzone": "5.7.4",
        "html-loader": "4.2.0",
        "axios": "0.27.2",
        "pinia-plugin-persist": "1.0.0",
        "vue-toastification": "^2.0.0-rc.5"
    }
}

webpack.config.js

import Dotenv from "dotenv-webpack"
import path from "path"
import MiniCssExtractPlugin from "mini-css-extract-plugin"
import CopyPlugin from "copy-webpack-plugin"
import webpack from "webpack"
import {VueLoaderPlugin} from "vue-loader"
import Autoprefixer from "autoprefixer"

export default (env, argv) => {
  console.log(`Running webpack in ${argv.mode} mode ...`);

  return [{
    // Watch for hot reload during development
    watchOptions: {
      aggregateTimeout: 200,
        poll: 600,
        ignored: /node_modules/,
    },
    resolve: {
      extensions: [
        ".ts",
        ".tsx",
        ".js",
        ".jsx",
        ".vue",
        ".scss"
      ],
      alias: {
        vue: (argv.mode === 'production') ? 'vue/dist/vue.runtime.esm-bundler.prod.js' : 'vue/dist/vue.runtime.esm-bundler.js'
      },
    },
    // Define the entry points of our application (can be multiple for different sections of a website)
    entry: {
      main: "./src/main.ts",
      "template.light": "./src/scss/template.light.scss",
      "template.dark": "./src/scss/template.dark.scss"
    },

    // Define the destination directory and filenames of compiled resources
    output: {
      filename: "js/[name].js",
      path: path.resolve(process.cwd(), "./public"),
    },

    // Define development options
    devtool: "source-map",

      // Define loaders
      module: {
    rules: [
      // Use babel for JS files
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        use: {
          loader: "babel-loader",
          options: {
            presets: [
              "@babel/preset-env"
            ],
            sourceMap: process.env.NODE_ENV !== 'production',
          }
        }
      },
      // CSS, PostCSS, and Sass
      {
        test: /\.(scss|css)$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: "css-loader",
            options: {
              importLoaders: 2,
              sourceMap: process.env.NODE_ENV !== 'production',
              url: false,
            }
          },
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  new Autoprefixer({
                    overrideBrowserslist: ['last 2 versions']
                  }),
                ]
              },
              sourceMap: process.env.NODE_ENV !== 'production',
            }
          },
          "sass-loader"
        ],
      },
      // File loader for images
      {
        test: /\.(jpg|jpeg|png)$/i,
        type: "asset/resource",
      },
      // Inline load SVG-s for use styles from css
      {
        test: /\.svg$/,
        use: [{ loader: 'html-loader' }]
      },
      {
        test: /.y(a?)ml$/,
        exclude: /node_modules/,
        loader: 'json-loader'
      },
      {
        test: /.y(a?)ml$/,
        exclude: /node_modules/,
        loader: 'yaml-loader'
      },
      {
        test: /\.ts(x?)$/,
        loader: "ts-loader",
        options: {
          configFile: path.resolve(process.cwd(), './tsconfig.json'),
          appendTsSuffixTo: [/\.vue$/],
        }
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          loaders: {
            ts: 'ts-loader',
            sourceMap: process.env.NODE_ENV !== 'production',
          },
          esModule: true
        }
      },
      {
        enforce: "pre",
        test: /\.[tj]s(x?)$/,
        loader: "source-map-loader",
        options: {
          filterSourceMappingUrl: (url, resourcePath) => {
            if (resourcePath.includes('rsdi')) {
              return false;
            }
            return true;
          },
        },
      },
      // For Pinia (https://github.com/vuejs/pinia/blob/v2/packages/docs/cookbook/migration-v1-v2.md#webpack-4-support)
      {
        test: /\.mjs$/,
        include: /node_modules/,
        type: 'javascript/auto',
      },
    ],
  },

    // Define used plugins
    plugins: [
      // Load .env file for environment variables in JS
      new Dotenv({
        path: "./.env"
      }),

      // Extracts CSS into separate files
      new MiniCssExtractPlugin({
        filename: "css/[name].css",
        chunkFilename: "[id].css"
      }),

      // Copy images to the public folder
      new CopyPlugin({
        patterns: [
          {
            from: "src/images",
            to: "images",
          }
        ]
      }),
      // For Vue.js
      new VueLoaderPlugin(),
      new webpack.DefinePlugin({
        __VUE_OPTIONS_API__: false,
        __VUE_PROD_DEVTOOLS__: false,
      }),
    ],
    // Performance configuration
    performance: {
    hints: false
  }
  }]
};

Environment

I also try to use next version without success.

Cause

As lllopo mentioned in issue-305 while your plugin states it is for the composition API, it internally uses the options API for the components. So, setting VUE_OPTIONS_API to false in webpack actually breaks it. And it was my case.

Temporary workaround

Set this

new webpack.DefinePlugin({
     __VUE_OPTIONS_API__: true,
}),

in webpack.config.js solves this issue, but It should be well documented in manual at least. It's a serous problem for all people trying to use this package with vue 3.

bad-mushroom commented 1 year ago

I've spent the last day trying to understand why my Toasts work in development but not production 😓 . This bug report led me to the answer... I had __VUE_OPTIONS_API__ explicitly false in my prod webpack build. Changing to true has my app Toast'ing again. Thank you!

rasteiner commented 1 year ago

Looks like the only place the options api is used is here: https://github.com/Maronato/vue-toastification/blob/b34ea31f76cb3204fcdd047c0214df77850afefa/src/components/VtToastContainer.vue#L215-L221

Every other component seems to only use <script setup> tags (or no <script> at all), I guess the snippet above could be safely removed?