vue.runtime.esm-browser.js 不渲染 Vue 3 组件

Saj*_*rai 2 vue.js vuejs3

我使用 Vue cli 创建了一个 vue 3 项目。我正在使用 webpack 配置来管理我的构建。当我将 vue 包指向 vue.runtime.esm-browser.js 时,我会在浏览器控制台中收到警告。“[Vue 警告]:组件提供了模板选项,但此 Vue 版本不支持运行时编译。请改用“vue.esm-browser.js”。”

当我检查文档时,有人提到“vue-loader”插件将 html 模板转换为呈现函数。看起来我缺少 webpack 所需的东西。

入口文件:main.js

import { createApp } from "vue";
import corecomponentA from "../core/components/corecomponentA.vue";

createApp({
  components: {
    "core-component-a": corecomponentA,
  },
}).mount("#app");
Run Code Online (Sandbox Code Playgroud)

webpack.config.js

var path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const { VueLoaderPlugin } = require("vue-loader");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;
const WebpackBar = require("webpackbar");

module.exports = (env, options) => {
  const devMode = options.mode != "production";
  return {
    entry: {
      "vue-bundle-store": "./src/entry/main.js",
    },
    output: {
      path: path.resolve(
        __dirname,
        "./../ui.clientlibs/src/js/"
      ),
      filename: "[name].js",
      chunkFilename: "[name].js",
      publicPath: process.env.BASE_URL,
    },

    module: {
      rules: [
        {
          enforce: "pre",
          test: /\.js$/,
          exclude: /node_modules/,
          loader: "eslint-loader",
        },
        {
          test: /\.vue$/,
          loader: "vue-loader",
        },
        {
          test: /\.js$/,
          loader: "babel-loader",
          exclude: "/node_modules/",
          query: {
            presets: ["@babel/preset-env"],
          },
        },
        {
          test: /\.ts$/,
          exclude: /node_modules/,
          use: [
            {
              loader: "babel-loader",
              options: { babelrc: true },
            },
            {
              loader: "ts-loader",
              options: { appendTsSuffixTo: [/\.vue$/] },
            },
          ],
        },
      ],
    },
    stats: {
      colors: true,
    },
    optimization: {
      splitChunks: {
        cacheGroups: {
          commons: {
            test: /[\\/]node_modules[\\/]/,
            name: "vendor-bundle",
            chunks: "all",
          },
        },
      },
      minimizer: !devMode
        ? [
            new UglifyJsPlugin({
              sourceMap: false,
              uglifyOptions: {
                chunkFilter: (chunk) => {
                  if (chunk.name === "vendor-bundle") {
                    return false;
                  }

                  return true;
                },
                compress: {
                  drop_console: true,
                },
                mangle: {
                  reserved: ["vueIns", "args", "el"],
                },
              },
            }),
          ]
        : [],
    },
    devtool: "source-map",    
    plugins: [      
      new CleanWebpackPlugin(),
      new VueLoaderPlugin(),
      new WebpackBar(),
      new BundleAnalyzerPlugin({
        analyzerPort: 4000,
        openAnalyzer: false,
        analyzerMode: "static",
      }),
    ] ,
    resolve: {
      extensions: [".ts", ".js", ".vue", ".json"],
      alias: {                
       vue: devMode ? "vue/dist/vue.runtime.esm-browser.js" : "vue/dist/vue.runtime.esm-browser.prod.js"
      }
    } 
  };
};

Run Code Online (Sandbox Code Playgroud)

核心组件A.vue

<script lang="ts">
import { h, ref, reactive } from "vue";

export default {
  setup() {
    const str = ref("Core component B");
    const object = reactive({ foo: "bar" });
    return () => h("div", [str.value, object.foo]);
  }
};
</script>

Run Code Online (Sandbox Code Playgroud)

包.json

{
  "name": "vue3.test",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "test:unit": "vue-cli-service test:unit",
    "lint": "vue-cli-service lint",
    "analyze-bundle": "webpack-bundle-analyzer stats.json",
    "bundle": "webpack --mode=production --env.production --config webpack.config.js",
    "bundle-dev": "webpack --mode=development --env.production=false --config webpack.config.js",
    "stats": "webpack --mode=production --env.production --config webpack.config.js --profile --json > stats.json"
  },
  "dependencies": {
    "vue": "^3.0.2"
  },
  "devDependencies": {
    "@types/jest": "^24.0.19",
    "@typescript-eslint/eslint-plugin": "^2.33.0",
    "@typescript-eslint/parser": "^2.33.0",
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-typescript": "~4.5.0",
    "@vue/cli-plugin-unit-jest": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.2",
    "@vue/eslint-config-prettier": "^6.0.0",
    "@vue/eslint-config-typescript": "^5.0.2",
    "@vue/test-utils": "^2.0.0-0",
    "clean-webpack-plugin": "^3.0.0",
    "core-js": "^3.6.5",
    "eslint": "^6.7.2",
    "eslint-plugin-prettier": "^3.1.3",
    "eslint-plugin-vue": "^7.0.0-0",
    "html-webpack-plugin": "^3.2.0",
    "prettier": "^1.19.1",
    "typescript": "~3.9.3",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "vue-jest": "^5.0.0-0",
    "vue-loader": "^16.0.0-beta.8",
    "webpack-cli": "^3.3.10",
    "webpackbar": "^4.0.0"
  }
}

Run Code Online (Sandbox Code Playgroud)

babel.config.js

module.exports = {
  ignore: [/\/core-js/],
  presets: [
    [
      "@babel/preset-env",
      { modules: false, useBuiltIns: "usage", corejs: "3.6.5" },
    ],
  ],
  overrides: [
    {
      test: "./node_modules",
      sourceType: "unambiguous",
    },
  ],
};

Run Code Online (Sandbox Code Playgroud)

在 html 文件中使用我的组件

<div id="app">
<core-component-a></core-component-a>
</div>

Run Code Online (Sandbox Code Playgroud)

该组件不会在浏览器中呈现。而是显示以下消息。

VM211871:1 [Vue warn]: Component provided template option but runtime compilation is not supported in this build of Vue. Use "vue.esm-browser.js" instead. 
  at <App>
Run Code Online (Sandbox Code Playgroud)

Jam*_*ruk 14

如果您使用 Vite,请添加别名 'vue': 'vue/dist/vue.esm-bundler'vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      'vue': 'vue/dist/vue.esm-bundler',
    },
  }
})
Run Code Online (Sandbox Code Playgroud)


Mic*_*evý 6

vue-loader 将 html 模板转换为仅在 SFC(单文件组件)中的渲染功能-.vue文件(从 Webpack 配置中的 vue 规则可以看出) - 并且仅在<template></template>SFC 块中提供模板

但是您的 HTML 文件中有一个模板 - 内容<div id="app">本质上是 Vue 模板。运行时 + 编译器与仅运行时

文档 vue.esm-bundler.js:包括运行时编译器。如果您正在使用捆绑器但仍需要运行时模板编译(例如,in-DOM 模板或通过内联 JavaScript 字符串的模板 - 组件template选项),请使用此选项。

此外,如果您使用 Webpack,则应该使用 Vue 的“bundler”版本

Webpack.config.js

alias: {                
       vue: "vue/dist/vue.esm-bundler.js"
}
Run Code Online (Sandbox Code Playgroud)

...您不需要切换 minified/dev 包,因为 Webpack 会(在正确配置时)以与您自己的代码相同的方式优化 Vue 代码。

另外,请注意文档中的这句话:Leaves prod/dev branch with process.env.NODE_ENVguards (must be changed by bundler)

NODE_ENV 通常用于定义环境类型,Vue 使用它来决定要包含哪些代码......

笔记

我真的不明白为什么你使用自己的 Webpack 配置来使用 Vue CLI 创建的项目,而 Vue CLI 的重点是为你管理 webpack 配置并提供大量选项来自定义它......没有任何意义