我正在开发一个前端使用 Nuxtjs 和 TailwindCss 的无头应用程序。在本地样式正常应用,但一旦部署到生产环境中,我可以在 html 中看到 tailwind 类,但没有应用/生成 CSS。这是我的配置。 包.json
{
"name": "nuxt-frontend",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "nuxt --port=$PORT",
"build": "~/.nvm/versions/node/v16.14.2/bin/node node_modules/nuxt/bin/nuxt.js build",
"start": "~/.nvm/versions/node/v16.14.2/bin/node node_modules/nuxt/bin/nuxt.js start --port=$PORT",
"generate": "~/.nvm/versions/node/v16.14.2/bin/node node_modules/nuxt/bin/nuxt.js generate",
"lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .",
"lint:style": "stylelint \"**/*.{vue,css}\" --ignore-path .gitignore",
"lint": "yarn lint:js && yarn lint:style"
},
"dependencies": {
"@nuxtjs/auth-next": "5.0.0-1637333559.35dbd53",
"@nuxtjs/axios": "^5.13.6",
"@nuxtjs/i18n": "^7.2.0",
"@nuxtjs/pwa": "^3.3.5",
"@rails/activestorage": "^7.0.4",
"buffer": "^6.0.3",
"core-js": "^3.15.1",
"lodash": "^4.17.21",
"nuxt": "^2.15.8",
"portal-vue": "^2.1.7",
"vue-slick-carousel": "^1.0.6",
"vue-tailwind": "^2.5.0",
"vue-mugen-scroll": "^0.2.6",
"vue-slick-carousel": "^1.0.6",
"vue-tailwind": "^2.5.0"
},
"devDependencies": {
"@babel/eslint-parser": "^7.14.7",
"@namics/stylelint-bem": "^7.0.0",
"@nuxtjs/eslint-config": "^10.0.0",
"@nuxtjs/eslint-module": "^3.1.0",
"@nuxtjs/stylelint-module": "^4.0.0",
"@nuxtjs/tailwindcss": "^4.2.0",
"@vue/eslint-config-standard": "^8.0.1",
"autoprefixer": "^10.4.7",
"eslint": "^8.19.0",
"eslint-plugin-jest": "^27.1.5",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-nuxt": "^3.2.0",
"eslint-plugin-vue": "^9.7.0",
"postcss": "^8.4.14",
"postcss-html": "^1.4.1",
"postcss-import": "^14.1.0",
"postcss-nesting": "^10.1.10",
"postcss-scss": "^4.0.4",
"stylelint": "^14.9.1",
"stylelint-config-standard": "^26.0.0",
"stylelint-config-standard-vue": "^1.0.0",
"stylelint-config-tailwindcss": "^0.0.6",
"tailwindcss": "^3.1.4"
}
}
Nuxt.config.js
const POLYFILL_FEATURES = [ // @see https://polyfill.io/v3/url-builder/
'default',
'es2015',
'es2016',
'es2017',
'es2018',
'es2019',
'es5',
'es6',
'IntersectionObserver', // @see https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-router#prefetchlinks
'window.scroll'
]
export default {
server: {
host: process.env.HOST || 'localhost',
port: process.env.PORT || 8080
},
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'Rails 7 Nuxt Template',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: 'Rails 7 Nuxt Template' },
{ name: 'format-detection', content: 'telephone=no' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
],
script: [
{ src: `https://polyfill.io/v3/polyfill.js?features=${POLYFILL_FEATURES.join('%2C')}`, body: true }
]
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
{ src: '~/plugins/vue-tailwind.js' },
{ src: '~/plugins/errors.js' },
{ src: '~/plugins/axios.js' },
{ src: '~/plugins/scrollPosition.js', mode: 'client' },
{ src: '~/plugins/scrollTo.js', mode: 'client' }
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: [
{ path: '~/components/AdminBackend', prefix: 'Admin' },
{ path: '~/components/Frontend', prefix: 'F' }
],
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
// https://go.nuxtjs.dev/eslint
'@nuxtjs/eslint-module',
// https://go.nuxtjs.dev/stylelint
'@nuxtjs/stylelint-module',
// https://tailwindcss.nuxtjs.org/
'@nuxtjs/tailwindcss'
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
// https://i18n.nuxtjs.org/
// https://github.com/nuxt-community/i18n-module
'@nuxtjs/i18n',
// https://go.nuxtjs.dev/axios
'@nuxtjs/axios',
// https://go.nuxtjs.dev/pwa
'@nuxtjs/pwa',
// https://dev.auth.nuxtjs.org/
'@nuxtjs/auth-next',
// https://github.com/LinusBorg/portal-vue
'portal-vue/nuxt',
// https://github.com/LinusBorg/portal-vue
'portal-vue/nuxt'
],
content: {
// intentionally blank
},
auth: {
strategies: {
local: {
token: {
property: 'token',
global: true
},
user: {
autoFetch: false,
property: 'user'
},
endpoints: {
login: {
url: '/api/auth/sign_in',
method: 'post',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
},
logout: {
url: '/api/auth/sign_out',
method: 'delete',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
},
user: {
url: '/api/auth/user',
method: 'get',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
}
}
}
},
redirect: {
login: '/login',
logout: '/login',
callback: '/login',
home: '/dashboard/'
},
plugins: ['~/plugins/auth/auth-i18n.js']
},
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {
proxy: true,
headers: {
common: {
'Content-Type': 'application/json',
Accept: 'application/json'
}
}
},
proxy: {
'/api/': {
target: process.env.RAILS_API_ENDPOINT,
pathRewrite: { '^/api/': '' }
},
'/rails/': {
target: process.env.RAILS_ENDPOINT
}
},
publicRuntimeConfig: {
baseUrl: process.env.BASE_URL,
directUploadsEndpoint: `${process.env.RAILS_ENDPOINT}/rails/active_storage/direct_uploads`
},
// PWA module configuration: https://go.nuxtjs.dev/pwa
pwa: {
manifest: {
lang: 'en'
}
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
extend (config, { isDev, isClient }) {
config.resolve.alias.vue = 'vue/dist/vue.common' // required for vue runtime compiler
},
html: {
minify: {
decodeEntities: false // @see nuxt-protected-mailto
}
},
postcss: {
// Add plugin names as key and arguments as value
// Install them before as dependencies with npm or yarn
plugins: {
// Disable a plugin by passing false as value
'postcss-import': {},
'tailwindcss/nesting': {},
autoprefixer: {}
}
},
transpile: [
'@rails/activestorage',
'defu'
]
},
tailwindcss: {
cssPath: '~/assets/css/tailwind.css'
},
extend (config, ctx) {
// Run ESLint on save
if (ctx.isDev && ctx.isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/,
options: {
fix: true
}
})
}
}
}
Tailwind.config.js
/** @type {import('tailwindcss').Config} */
const screens = require('./tailwind-breakpoints.config.js')
module.exports = {
// purge: {
content: [
'./components/**/*.{vue,js}',
'./content/**/*.md',
'./layouts/**/*.vue',
'./pages/**/*.vue',
'./plugins/**/*.{js,ts}',
'./nuxt.config.{js,ts}'
],
// },
darkMode: false, // or 'media' or 'class'
theme: {
screens,
extend: {
colors: {
blue: {
font: '#335DB0',
button: '#335DB0'
},
grey: {
accent: '#D9D9D9',
bg: '#F5F5F5',
profile_pic: '#757575'
},
red: {
inactive: '#E25151'
},
green: {
active: '#91E251'
}
}
}
},
plugins: [
function ({ addBase, theme }) {
const screens = theme('screens', {})
const breakpoints = Object.keys(screens)
addBase({
':root': {
'--current-breakpoint': 0
},
...breakpoints.reduce((acc, current) => {
acc[`@media (min-width: ${screens[current]})`] = {
':root': {
'--current-breakpoint': screens[current]
}
}
return acc
}, {})
})
}
]
}
如果有人知道我做错了什么,请帮助我。
在
nuxt.config.js
中的build property
我已将postcss
由postcssOptions
重命名并添加了
extractCSS: {
ignoreOrder: true
},
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.(css|vue)$/,
chunks: 'all',
enforce: true
}
}
}
},
nuxt.config.js
现在看起来像这样
const POLYFILL_FEATURES = [ // @see https://polyfill.io/v3/url-builder/
'default',
'es2015',
'es2016',
'es2017',
'es2018',
'es2019',
'es5',
'es6',
'IntersectionObserver', // @see https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-router#prefetchlinks
'window.scroll'
]
export default {
server: {
host: process.env.HOST || 'localhost',
port: process.env.PORT || 8080
},
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'Rails 7 Nuxt Template',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: 'Rails 7 Nuxt Template' },
{ name: 'format-detection', content: 'telephone=no' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
],
script: [
{ src: `https://polyfill.io/v3/polyfill.js?features=${POLYFILL_FEATURES.join('%2C')}`, body: true }
]
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
{ src: '~/plugins/vue-tailwind.js' },
{ src: '~/plugins/errors.js' },
{ src: '~/plugins/axios.js' },
{ src: '~/plugins/scrollPosition.js', mode: 'client' },
{ src: '~/plugins/scrollTo.js', mode: 'client' }
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: [
{ path: '~/components/AdminBackend', prefix: 'Admin' },
{ path: '~/components/Frontend', prefix: 'F' }
],
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
// https://go.nuxtjs.dev/eslint
'@nuxtjs/eslint-module',
// https://go.nuxtjs.dev/stylelint
'@nuxtjs/stylelint-module',
// https://tailwindcss.nuxtjs.org/
'@nuxtjs/tailwindcss'
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
// https://i18n.nuxtjs.org/
// https://github.com/nuxt-community/i18n-module
'@nuxtjs/i18n',
// https://go.nuxtjs.dev/axios
'@nuxtjs/axios',
// https://go.nuxtjs.dev/pwa
'@nuxtjs/pwa',
// https://dev.auth.nuxtjs.org/
'@nuxtjs/auth-next',
// https://github.com/LinusBorg/portal-vue
'portal-vue/nuxt'
],
content: {
// intentionally blank
},
auth: {
strategies: {
local: {
token: {
property: 'token',
global: true
},
user: {
autoFetch: false,
property: 'user'
},
endpoints: {
login: {
url: '/api/auth/sign_in',
method: 'post',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
},
logout: {
url: '/api/auth/sign_out',
method: 'delete',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
},
user: {
url: '/api/auth/user',
method: 'get',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
}
}
}
},
redirect: {
login: '/login',
logout: '/login',
callback: '/login',
home: '/dashboard/'
},
plugins: ['~/plugins/auth/auth-i18n.js']
},
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {
proxy: true,
headers: {
common: {
'Content-Type': 'application/json',
Accept: 'application/json'
}
}
},
proxy: {
'/api/': {
target: process.env.RAILS_API_ENDPOINT,
pathRewrite: { '^/api/': '' }
},
'/rails/': {
target: process.env.RAILS_ENDPOINT
}
},
publicRuntimeConfig: {
baseUrl: process.env.BASE_URL,
directUploadsEndpoint: `${process.env.RAILS_ENDPOINT}/rails/active_storage/direct_uploads`
},
// PWA module configuration: https://go.nuxtjs.dev/pwa
pwa: {
manifest: {
lang: 'en'
}
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
extend (config, { isDev, isClient }) {
config.resolve.alias.vue = 'vue/dist/vue.common' // required for vue runtime compiler
},
html: {
minify: {
decodeEntities: false // @see nuxt-protected-mailto
}
},
extractCSS: {
ignoreOrder: true
},
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.(css|vue)$/,
chunks: 'all',
enforce: true
}
}
}
},
postcssOptions: {
// Add plugin names as key and arguments as value
// Install them before as dependencies with npm or yarn
plugins: {
// Disable a plugin by passing false as value
'postcss-import': {},
'tailwindcss/nesting': {},
autoprefixer: {}
}
},
transpile: [
'@rails/activestorage',
'defu'
]
},
extend (config, ctx) {
// Run ESLint on save
if (ctx.isDev && ctx.isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/,
options: {
fix: true
}
})
}
}
}