Vuetify CSS 在我为生产构建时丢失
Vuetify CSS missing when i build for production
我们从某人那里购买了一个用 Vue 编写的 Web 应用程序,我们正在开发它 change/improve。我们添加的一件事是 Vuetify,因此我们可以使用 Vuetify 元素,并且在开发模式下一切都运行良好,但是当我们为生产构建时,缺少 Vuetify 元素的 CSS。
我已经在网上搜索过了,并且已经尝试了大家的建议,但没有成功。
任何人都知道可能出了什么问题以及为什么 npm 运行 build 会缺少一些 CSS?
奇怪的是 Vue 元素的所有 UI 功能都运行良好,只是缺少 CSS。
请参阅下面的代码示例。
main.js:
import '@fortawesome/fontawesome-free/css/all.css'
import Vue from "vue";
import App from "./App.vue";
import VueMoment from "vue-moment";
import VueAnalytics from "vue-analytics";
import VueMeta from "vue-meta";
import { library } from "@fortawesome/fontawesome-svg-core";
import {
faCoffee,
faPlusCircle,
faChartLine,
faChevronDown,
faMobile,
faEnvelope,
faClock,
faUsers,
faPaperPlane,
faCheckCircle,
faCheck,
faLeaf,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import axios from "axios";
import router from "./router";
import store from "./store";
import vuetify from './plugins/vuetify';
import Vuetify from 'vuetify/lib'
library.add([
faCoffee,
faPlusCircle,
faChartLine,
faChevronDown,
faMobile,
faEnvelope,
faClock,
faUsers,
faPaperPlane,
faCheckCircle,
faCheck,
faLeaf,
]);
Vue.use(VueAnalytics, {
id: "xxx",
router,
});
Vue.use(VueMoment);
Vue.use(VueMeta);
Vue.component("font-awesome-icon", FontAwesomeIcon);
Vue.use(Vuetify)
axios.interceptors.response.use(undefined, async function (error) {
if (error.response.status === 401) {
await store.dispatch("auth/logout");
router.push("/login");
}
return Promise.reject(error);
});
// Plugins
// ...
// Sass file
require("./assets/styles/main.css");
Vue.config.productionTip = false;
new Vue({
router,
store,
vuetify,
render: (h) => h(App)
}).$mount("#app");
App.vue:
<template>
<v-app>
<v-main>
<router-view/>
</v-main>
</v-app>
</template>
<style>
.text-white {
color: #fff !important;
}
.text-gray-600 {
color: #757575 !important;
}
.font-semibold, .text-gray-700 {
color: #616161 !important;
}
</style>
package.json:
{
"name": "reviewgrower-spa",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"deploy": "git push dokku master"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.25",
"@fortawesome/free-solid-svg-icons": "^5.11.2",
"@fortawesome/vue-fontawesome": "^0.1.8",
"@fullhuman/postcss-purgecss": "^1.3.0",
"axios": "^0.19.0",
"chart.js": "^2.9.4",
"core-js": "^2.6.10",
"i": "^0.3.6",
"jquery": "^3.5.1",
"npm": "^6.13.0",
"tailwindcss-spinner": "^0.2.0",
"tailwindcss-toggle": "github:TowelSoftware/tailwindcss-toggle",
"url-parse": "^1.4.7",
"vue": "^2.6.10",
"vue-analytics": "^5.17.2",
"vue-chartjs": "^3.5.1",
"vue-click-outside": "^1.0.7",
"vue-clickaway": "^2.2.2",
"vue-feather-icons": "^4.22.0",
"vue-js-toggle-button": "^1.3.3",
"vue-meta": "^1.6.0",
"vue-moment": "^4.0.0",
"vue-router": "^3.1.3",
"vue-stripe-elements-plus": "^0.2.10",
"vuetify": "^2.4.0",
"vuex": "^3.0.1",
"vuex-persist": "^2.1.1"
},
"devDependencies": {
"@fortawesome/fontawesome-free": "^5.15.2",
"@vue/cli-plugin-babel": "^3.12.1",
"@vue/cli-plugin-eslint": "^3.12.1",
"@vue/cli-service": "^3.12.1",
"babel-eslint": "^10.0.3",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.2.3",
"sass": "^1.32.0",
"sass-loader": "^7.1.0",
"tailwindcss": "^1.1.3",
"vue-cli-plugin-vuetify": "~2.1.0",
"vue-template-compiler": "^2.5.21",
"vuetify-loader": "^1.7.0"
}
}
很难理解哪里缺少了什么。如果您认为缺少,请尝试从 cdn 将 css 添加到 HTML 文件并检查工作情况。
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
我看到你使用的是webpack来编译代码。所以,这也可能与 webpack 配置有关。在你的 webpack 规则中,你有 css 和 scss 的规则吗?因为 vuetify 文件在 scss.
当我做这些类型的马戏团时,我的 webpack 配置如下。
--webpack.config.js--
const path = require("path");
const VuetifyLoaderPlugin = require("vuetify-loader/lib/plugin");
const { VueLoaderPlugin } = require("vue-loader");
module.exports = {
watch: true,
entry: {
main: 'main.js'
},
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.vue$/,
use: "vue-loader",
},
{
test: /\.s(c|a)ss$/,
use: [
"vue-style-loader",
"css-loader",
{
loader: "sass-loader",
// Requires sass-loader@^8.0.0
// options: {
// implementation: require('sass'),
// sassOptions: {
// fiber: require('fibers'),
// indentedSyntax: true // optional
// },
// },
},
],
},
],
},
plugins: [
new VueLoaderPlugin(),
new VuetifyLoaderPlugin({
/**
* This function will be called for every tag used in each vue component
* It should return an array, the first element will be inserted into the
* components array, the second should be a corresponding import
*
* originalTag - the tag as it was originally used in the template
* kebabTag - the tag normalised to kebab-case
* camelTag - the tag normalised to PascalCase
* path - a relative path to the current .vue file
* component - a parsed representation of the current component
*/
match(originalTag, { kebabTag, camelTag, path, component }) {
if (kebabTag.startsWith("core-")) {
return [
camelTag,
`import ${camelTag} from '@/components/core/${camelTag.substring(
4
)}.vue'`,
];
}
},
}),
],
}
检查一下你的postcss.config.js,看看是不是跟purgecss有关。
您必须配置白名单以忽略 vuetify 样式。
这里有一个示例供您参考:
const autoprefixer = require("autoprefixer");
const postcssImport = require("postcss-import");
const purgecss = require("@fullhuman/postcss-purgecss");
const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV);
let plugins = [];
if (IS_PROD) {
plugins.push(postcssImport);
plugins.push(
purgecss({
content: [
"./src/**/*.vue",
"./public/**/*.html",
`./node_modules/vuetify/src/**/*.ts`,
`./node_modules/vuetify/dist/vuetify.css`
],
defaultExtractor (content) {
const contentWithoutStyleBlocks = content.replace(/<style[^]+?<\/style>/gi, '')
return contentWithoutStyleBlocks.match(/[A-Za-z0-9-_/:]*[A-Za-z0-9-_/]+/g) || []
},
safelist: [ /-(leave|enter|appear)(|-(to|from|active))$/, /^(?!(|.*?:)cursor-move).+-move$/, /^router-link(|-exact)-active$/, /data-v-.*/ ],
whitelist: [
'container',
'row',
'spacer',
'aos-animate',
'col',
'[type=button]',
'v-application p',
],
whitelistPatterns: [
/^v-.*/,
/^col-.*/,
/^theme-.*/,
/^rounded-.*/,
/^data-aos-.*/,
/^(red|grey)--text$/,
/^text--darken-[1-4]$/,
/^text--lighten-[1-4]$/
],
whitelistPatternsChildren: [
/^post-content/,
/^v-input/,
/^swiper-.*/,
/^pswp.*/,
/^v-text-field.*/,
/^v-progress-linear/
]
})
);
}
module.exports = {
plugins:[
require('cssnano')({
preset: 'default'
}),
require('postcss-pxtorem')({
remUnit:15, //每个rem对应的px值
threeVersion:true
}),
...plugins,autoprefixer
]
}``
您只是缺少 main.js
中的一个包含(请参阅 vuetify docs):
import 'vuetify/dist/vuetify.min.css'
这将确保 webpack 在捆绑的 CSS 中包含 vuetify 样式以用于生产。这为我解决了同样的问题(即它在本地有效但在生产中无效)。
我们从某人那里购买了一个用 Vue 编写的 Web 应用程序,我们正在开发它 change/improve。我们添加的一件事是 Vuetify,因此我们可以使用 Vuetify 元素,并且在开发模式下一切都运行良好,但是当我们为生产构建时,缺少 Vuetify 元素的 CSS。
我已经在网上搜索过了,并且已经尝试了大家的建议,但没有成功。
任何人都知道可能出了什么问题以及为什么 npm 运行 build 会缺少一些 CSS?
奇怪的是 Vue 元素的所有 UI 功能都运行良好,只是缺少 CSS。
请参阅下面的代码示例。
main.js:
import '@fortawesome/fontawesome-free/css/all.css'
import Vue from "vue";
import App from "./App.vue";
import VueMoment from "vue-moment";
import VueAnalytics from "vue-analytics";
import VueMeta from "vue-meta";
import { library } from "@fortawesome/fontawesome-svg-core";
import {
faCoffee,
faPlusCircle,
faChartLine,
faChevronDown,
faMobile,
faEnvelope,
faClock,
faUsers,
faPaperPlane,
faCheckCircle,
faCheck,
faLeaf,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import axios from "axios";
import router from "./router";
import store from "./store";
import vuetify from './plugins/vuetify';
import Vuetify from 'vuetify/lib'
library.add([
faCoffee,
faPlusCircle,
faChartLine,
faChevronDown,
faMobile,
faEnvelope,
faClock,
faUsers,
faPaperPlane,
faCheckCircle,
faCheck,
faLeaf,
]);
Vue.use(VueAnalytics, {
id: "xxx",
router,
});
Vue.use(VueMoment);
Vue.use(VueMeta);
Vue.component("font-awesome-icon", FontAwesomeIcon);
Vue.use(Vuetify)
axios.interceptors.response.use(undefined, async function (error) {
if (error.response.status === 401) {
await store.dispatch("auth/logout");
router.push("/login");
}
return Promise.reject(error);
});
// Plugins
// ...
// Sass file
require("./assets/styles/main.css");
Vue.config.productionTip = false;
new Vue({
router,
store,
vuetify,
render: (h) => h(App)
}).$mount("#app");
App.vue:
<template>
<v-app>
<v-main>
<router-view/>
</v-main>
</v-app>
</template>
<style>
.text-white {
color: #fff !important;
}
.text-gray-600 {
color: #757575 !important;
}
.font-semibold, .text-gray-700 {
color: #616161 !important;
}
</style>
package.json:
{
"name": "reviewgrower-spa",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"deploy": "git push dokku master"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.25",
"@fortawesome/free-solid-svg-icons": "^5.11.2",
"@fortawesome/vue-fontawesome": "^0.1.8",
"@fullhuman/postcss-purgecss": "^1.3.0",
"axios": "^0.19.0",
"chart.js": "^2.9.4",
"core-js": "^2.6.10",
"i": "^0.3.6",
"jquery": "^3.5.1",
"npm": "^6.13.0",
"tailwindcss-spinner": "^0.2.0",
"tailwindcss-toggle": "github:TowelSoftware/tailwindcss-toggle",
"url-parse": "^1.4.7",
"vue": "^2.6.10",
"vue-analytics": "^5.17.2",
"vue-chartjs": "^3.5.1",
"vue-click-outside": "^1.0.7",
"vue-clickaway": "^2.2.2",
"vue-feather-icons": "^4.22.0",
"vue-js-toggle-button": "^1.3.3",
"vue-meta": "^1.6.0",
"vue-moment": "^4.0.0",
"vue-router": "^3.1.3",
"vue-stripe-elements-plus": "^0.2.10",
"vuetify": "^2.4.0",
"vuex": "^3.0.1",
"vuex-persist": "^2.1.1"
},
"devDependencies": {
"@fortawesome/fontawesome-free": "^5.15.2",
"@vue/cli-plugin-babel": "^3.12.1",
"@vue/cli-plugin-eslint": "^3.12.1",
"@vue/cli-service": "^3.12.1",
"babel-eslint": "^10.0.3",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.2.3",
"sass": "^1.32.0",
"sass-loader": "^7.1.0",
"tailwindcss": "^1.1.3",
"vue-cli-plugin-vuetify": "~2.1.0",
"vue-template-compiler": "^2.5.21",
"vuetify-loader": "^1.7.0"
}
}
很难理解哪里缺少了什么。如果您认为缺少,请尝试从 cdn 将 css 添加到 HTML 文件并检查工作情况。
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
我看到你使用的是webpack来编译代码。所以,这也可能与 webpack 配置有关。在你的 webpack 规则中,你有 css 和 scss 的规则吗?因为 vuetify 文件在 scss.
当我做这些类型的马戏团时,我的 webpack 配置如下。
--webpack.config.js--
const path = require("path");
const VuetifyLoaderPlugin = require("vuetify-loader/lib/plugin");
const { VueLoaderPlugin } = require("vue-loader");
module.exports = {
watch: true,
entry: {
main: 'main.js'
},
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.vue$/,
use: "vue-loader",
},
{
test: /\.s(c|a)ss$/,
use: [
"vue-style-loader",
"css-loader",
{
loader: "sass-loader",
// Requires sass-loader@^8.0.0
// options: {
// implementation: require('sass'),
// sassOptions: {
// fiber: require('fibers'),
// indentedSyntax: true // optional
// },
// },
},
],
},
],
},
plugins: [
new VueLoaderPlugin(),
new VuetifyLoaderPlugin({
/**
* This function will be called for every tag used in each vue component
* It should return an array, the first element will be inserted into the
* components array, the second should be a corresponding import
*
* originalTag - the tag as it was originally used in the template
* kebabTag - the tag normalised to kebab-case
* camelTag - the tag normalised to PascalCase
* path - a relative path to the current .vue file
* component - a parsed representation of the current component
*/
match(originalTag, { kebabTag, camelTag, path, component }) {
if (kebabTag.startsWith("core-")) {
return [
camelTag,
`import ${camelTag} from '@/components/core/${camelTag.substring(
4
)}.vue'`,
];
}
},
}),
],
}
检查一下你的postcss.config.js,看看是不是跟purgecss有关。 您必须配置白名单以忽略 vuetify 样式。 这里有一个示例供您参考:
const autoprefixer = require("autoprefixer");
const postcssImport = require("postcss-import");
const purgecss = require("@fullhuman/postcss-purgecss");
const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV);
let plugins = [];
if (IS_PROD) {
plugins.push(postcssImport);
plugins.push(
purgecss({
content: [
"./src/**/*.vue",
"./public/**/*.html",
`./node_modules/vuetify/src/**/*.ts`,
`./node_modules/vuetify/dist/vuetify.css`
],
defaultExtractor (content) {
const contentWithoutStyleBlocks = content.replace(/<style[^]+?<\/style>/gi, '')
return contentWithoutStyleBlocks.match(/[A-Za-z0-9-_/:]*[A-Za-z0-9-_/]+/g) || []
},
safelist: [ /-(leave|enter|appear)(|-(to|from|active))$/, /^(?!(|.*?:)cursor-move).+-move$/, /^router-link(|-exact)-active$/, /data-v-.*/ ],
whitelist: [
'container',
'row',
'spacer',
'aos-animate',
'col',
'[type=button]',
'v-application p',
],
whitelistPatterns: [
/^v-.*/,
/^col-.*/,
/^theme-.*/,
/^rounded-.*/,
/^data-aos-.*/,
/^(red|grey)--text$/,
/^text--darken-[1-4]$/,
/^text--lighten-[1-4]$/
],
whitelistPatternsChildren: [
/^post-content/,
/^v-input/,
/^swiper-.*/,
/^pswp.*/,
/^v-text-field.*/,
/^v-progress-linear/
]
})
);
}
module.exports = {
plugins:[
require('cssnano')({
preset: 'default'
}),
require('postcss-pxtorem')({
remUnit:15, //每个rem对应的px值
threeVersion:true
}),
...plugins,autoprefixer
]
}``
您只是缺少 main.js
中的一个包含(请参阅 vuetify docs):
import 'vuetify/dist/vuetify.min.css'
这将确保 webpack 在捆绑的 CSS 中包含 vuetify 样式以用于生产。这为我解决了同样的问题(即它在本地有效但在生产中无效)。