【问题标题】:vue.runtime.esm-browser.js does not render Vue 3 componentsvue.runtime.esm-browser.js 不渲染 Vue 3 组件
【发布时间】:2021-02-03 23:55:56
【问题描述】:

我使用 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");

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"
      }
    } 
  };
};

coreComponentA.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>

package.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"
  }
}

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",
    },
  ],
};

在 html 文件中使用我的组件

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

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

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>

【问题讨论】:

  • 我也面临同样的问题

标签: vue.js vuejs3


【解决方案1】:

vue-loader 仅在 SFC(单一文件组件)-.vue 文件中将 html 模板转换为呈现函数(从 Webpack 配置中的 vue 规则可以看出)-和 仅在&lt;template&gt;&lt;/template&gt; SFC 块中提供的模板

但是您的 HTML 文件中有一个模板 - &lt;div id="app"&gt; 的内容本质上是 Vue 模板。 Runtime + Compiler vs. Runtime-only

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

另外,如果你使用 Webpack,你应该使用“捆绑器”版本的 Vue

Webpack.config.js

alias: {                
       vue: "vue/dist/vue.esm-bundler.js"
}

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

另外,请注意文档中的这句话:用process.env.NODE_ENV 守卫离开 prod/dev 分支(必须用 bundler 替换)

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

注意

我真的不明白,当 Vue CLI 的全部目的是为你管理 webpack 配置并为 customize it... 提供大量选项时,我真的不明白你为什么要为使用 Vue CLI 创建的项目使用自己的 Webpack 配置。没有任何意义

【讨论】:

  • 谢谢。这确实有助于解决我的问题。
  • 如果我添加 alias: { vue:"@vue/runtime-dom" } 作为别名,就会发生摇树。但是如果我将别名添加为alias: { vue:"vue/dist/vue.esm-browser.prod.js", },则不会发生摇树。如果我使用 vue-esm-browser.prod.js,有没有办法摇树?
  • 没有。 browser build 具有与 global build 相同的所有依赖项内联(请参阅我的答案中的文档链接)。当文档告诉您使用bundler 版本时,您为什么要使用browser 与Webpack 一起构建?
  • 捆绑器版本将@babel/parser/lib 添加到我的供应商捆绑包中,它的大小非常重。
  • 这真的很奇怪。也许它与文档中的这句话有关:Leaves prod/dev branches with process.env.NODE_ENV guards (must be replaced by bundler)。您是否尝试使用(某种)标准 NODE_ENV='production' ENV 变量而不是您自己的?
猜你喜欢
  • 2023-02-03
  • 2022-01-18
  • 1970-01-01
  • 2021-03-10
  • 1970-01-01
  • 2021-05-04
  • 2021-09-19
  • 2017-03-21
  • 1970-01-01
相关资源
最近更新 更多