Jon*_*ers 2 javascript next.js tailwind-css css-purge
在我当前的 NextJS 项目中,我使用 Tailwind 作为 CSS 框架。当我运行时yarn dev,一切正常,但是每当我运行yarn build后跟 a 时yarn start,我的所有 CSS 似乎都被清除了,因为我的页面布局完全不同。
我的 tailwind.config.js 文件:
/* eslint-disable global-require */
const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = {
purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
darkMode: false, // or 'media' or 'class'
theme: {
screens: {
sm: '640px',
md: '768px',
max_md: { max: '767px' },
lg: '1024px',
xl: '1536px',
},
colors: {
primary: '#f2a53f',
white: '#fff',
},
fontFamily: {
title: ['Dancing Script', 'Times New Roman', 'sans-serif'],
sans: ['Roboto', ...defaultTheme.fontFamily.sans],
},
textShadow: {
default: '1px 1px 3px #000',
},
zIndex: {
1: -1,
},
extend: {
height: {
128: '32rem',
},
margin: {},
},
},
variants: {
extend: {},
},
plugins: [require('tailwindcss-textshadow')],
};
Run Code Online (Sandbox Code Playgroud)
postcss.config.js 文件:
const purgecss = [
'@fullhuman/postcss-purgecss',
{
content: [
'./pages/**/*.{js,jsx,ts,tsx}',
'./components/**/*.{js,jsx,ts,tsx}',
],
defaultExtractor: (content) => content.match(/[\w-/:]+(?<!:)/g) || [],
},
];
module.exports = {
plugins: [
'tailwindcss',
process.env.NODE_ENV === 'production' ? purgecss : undefined,
],
};
Run Code Online (Sandbox Code Playgroud)
_app.tsx:
import Head from 'next/head';
import { ApolloProvider } from '@apollo/client';
import { AppProps } from 'next/app';
import { useApollo } from '../../apollo/client';
import '../styles/globals.css';
const MyApp = ({ Component, pageProps }: AppProps) => (
<ApolloProvider client={useApollo(pageProps.initialApolloState)}>
<Component {...pageProps} />
</ApolloProvider>
);
export default MyApp;
Run Code Online (Sandbox Code Playgroud)
globals.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
@font-face {
font-family: 'Dancing Script';
font-style: medium;
font-weight: 500;
font-display: swap;
src: local('Dancing Script'),
url(/fonts/DancingScript-Medium.tff) format('tff');
}
body {
margin: 0 !important;
}
Run Code Online (Sandbox Code Playgroud)
package.json 依赖项:
"dependencies": {
"@apollo/client": "3.3.12",
"@apollo/react-hooks": "4.0.0",
"@contentful/rich-text-react-renderer": "14.1.2",
"@contentful/rich-text-types": "14.1.2",
"apollo-cache-inmemory": "1.6.6",
"apollo-client": "2.6.10",
"apollo-link-http": "1.5.17",
"autoprefixer": "10.2.5",
"clsx": "1.1.1",
"contentful": "8.2.0",
"graphql": "15.5.0",
"graphql-tag": "2.11.0",
"next": "10.0.9",
"next-with-apollo": "5.1.1",
"postcss": "8.2.8",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-icons": "4.2.0",
"tailwindcss": "2.0.4",
"tailwindcss-textshadow": "2.1.3"
},
"devDependencies": {
"@commitlint/cli": "12.0.1",
"@commitlint/config-conventional": "12.0.1",
"@fullhuman/postcss-purgecss": "4.0.3",
"@types/node": "14.14.35",
"@types/react": "17.0.3",
"@types/react-dom": "17.0.2",
"@typescript-eslint/eslint-plugin": "4.18.0",
"@typescript-eslint/parser": "4.18.0",
"add": "2.0.6",
"commitizen": "4.2.3",
"cz-conventional-changelog": "3.3.0",
"eslint": "7.22.0",
"eslint-config-airbnb": "18.2.1",
"eslint-config-prettier": "8.1.0",
"eslint-import-resolver-typescript": "2.4.0",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-jsx-a11y": "6.4.1",
"eslint-plugin-prettier": "3.3.1",
"eslint-plugin-react": "7.22.0",
"eslint-plugin-react-hooks": "4.2.0",
"husky": "5.1.3",
"lint-staged": "10.5.4",
"postcss-preset-env": "6.7.0",
"prettier": "2.2.1",
"typescript": "4.2.3",
"yarn": "1.22.10"
},
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
}
Run Code Online (Sandbox Code Playgroud)
如果有任何不妥之处,请随时告诉我。我在网上查看了其他问题,但没有找到解决我的问题的方法。
仔细检查tailwind.config.js. 如果您的组件不在components目录中,那么您需要更新purge路径以反映这一点。
我想我看到了这个问题。@fullhuman/postcss-purgecss从 v1.4 左右开始就与 tailwindcss 捆绑在一起。由于它也是在您的 postcss 文件中手动声明的,因此它会被执行两次,从而擦除您的所有样式。此外,它仅在生产中擦除您的样式这一事实表明它是罪魁祸首,因为该特定包的执行依赖于process.env.NODE_ENV===production. 从 postcss 文件中删除它应该可以解决您的问题,因为它已经由 tailwindcss 包在后台执行。
这是我的 postcss 进行tailwindcss@2.0.3比较:
postcss.config.js
module.exports = {
plugins: [
'postcss-import',
'tailwindcss',
'postcss-nesting',
'postcss-flexbugs-fixes',
[
'postcss-preset-env',
{
autoprefixer: {
flexbox: 'no-2009'
},
stage: 3,
features: {
'custom-properties': false,
'nesting-rules': true
}
}
]
]
};
Run Code Online (Sandbox Code Playgroud)
另一种可能性是您没有将要清除的路径/文件类型包装在顶级content对象中。从为您的文件提供的代码tailwind.config.js:
module.exports = {
purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
//...
}
Run Code Online (Sandbox Code Playgroud)
这是我的tailwind.config.js交叉比较
const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = {
important: true,
purge: {
content: [
'./components/**/*.{js,ts,jsx,tsx}',
'./pages/**/*.{js,ts,jsx,tsx}'
],
options: {
safelist: {
standard: ['outline-none']
}
}
},
darkMode: 'class',
theme: {
lineClamp: {
1: 1,
2: 2,
3: 3,
4: 4
},
extend: {
zIndex: {
'-10': '-10',
100: '100',
150: '150'
},
maxWidth: {
'9xl': '121rem', // 1936px
'8xl': '96rem' // 1536px
},
screens: {
xs: '375px',
sm: '640px',
md: '768px',
lg: '1024px',
xl: '1280px',
'2xl': '1440px',
'3xl': '1920px'
},
transitionDuration: {
0: '0ms',
300: '300ms',
500: '500ms',
700: '700ms',
1000: '1000ms'
},
rotate: {
0: '0deg',
45: '45deg',
90: '90deg',
125: '125deg',
180: '180deg',
270: '270deg',
360: '360deg'
},
fontFamily: {
header: ['goudy-bookletter-1911', 'serif'],
poppins: ['poppins', 'sans-serif'],
somaRoman: ['neue-haas-grotesk-text', 'sans-serif'],
somaDisplay: ['neue-haas-grotesk-display', 'sans-serif'],
sans: ['Inter var', ...defaultTheme.fontFamily.sans]
},
colors: {
'reddit-0': 'var(--reddit-0)',
'reddit-1': 'var(--reddit-1)',
'reddit-2': 'var(--reddit-2)',
'reddit-3': 'var(--reddit-3)',
'reddit-4': 'var(--reddit-4)',
'primary-0': 'var(--primary-0)',
'primary-1': 'var(--primary-1)',
'primary-2': 'var(--primary-2)',
'primary-3': 'var(--primary-3)',
'primary-4': 'var(--primary-4)',
'primary-5': 'var(--primary-5)',
'primary-6': 'var(--primary-6)',
'primary-7': 'var(--primary-7)',
'primary-8': 'var(--primary-8)',
'primary-9': 'var(--primary-9)',
'secondary-0': 'var(--secondary-0)',
'secondary-1': 'var(--secondary-1)',
'secondary-2': 'var(--secondary-2)',
'accents-0': 'var(--accents-0)',
'accents-1': 'var(--accents-1)',
'accents-2': 'var(--accents-2)',
'accents-3': 'var(--accents-3)',
'accents-4': 'var(--accents-4)',
'accents-5': 'var(--accents-5)',
'accents-6': 'var(--accents-6)',
'accents-7': 'var(--accents-7)',
'accents-8': 'var(--accents-8)',
'accents-9': 'var(--accents-9)',
'theme-0': 'var(--theme-0)',
'theme-1': 'var(--theme-1)',
lightBlue: {
0: '#E3F8FF',
100: '#B3ECFF',
200: '#81DEFD',
300: '#5ED0FA',
400: '#40C3F7',
500: '#2BB0ED',
600: '#1992D4',
700: '#127FBF',
800: '#0B69A3',
900: '#035388'
},
cyan: {
0: '#E0FCFF',
100: '#BEF8FD',
200: '#87EAF2',
300: '#54D1DB',
400: '#38BEC9',
500: '#2CB1BC',
600: '#14919B',
700: '#0E7C86',
800: '#0A6C74',
900: '#044E54'
},
rojo: {
0: '#610316',
100: '#8A041A',
200: '#AB091E',
300: '#CF1124',
400: '#E12D39',
500: '#EF4E4E',
600: '#F86A6A',
700: '#FF9B9B',
800: '#FFBDBD',
900: '#FFE3E3'
},
rosado: {
0: '#620042',
100: '#870557',
200: '#A30664',
300: '#BC0A6F',
400: '#DA127D',
500: '#E8368F',
600: '#F364A2',
700: '#FF8CBA',
800: '#FFB8D2',
900: '#FFE3EC'
},
amarillo: {
0: 'hsl(15, 86%, 30%)',
100: 'hsl(22, 82%, 39%)',
200: 'hsl(29, 80%, 44%)',
300: 'hsl(36, 77%, 49%)',
400: 'hsl(42, 87%, 55%)',
500: 'hsl(44, 92%, 63%)',
600: 'hsl(48, 94%, 68%)',
700: 'hsl(48, 95%, 76%)',
800: 'hsl(48, 100%, 88%)',
900: 'hsl(49, 100%, 96%)'
},
verdeAzulado: {
// blueish-green === teal (espanol)
0: 'hsl(170, 97%, 15%)',
100: 'hsl(168, 80%, 23%)',
200: 'hsl(166, 72%, 28%)',
300: 'hsl(164, 71%, 34%)',
400: 'hsl(162, 63%, 41%)',
500: 'hsl(160, 51%, 49%)',
600: 'hsl(158, 58%, 62%)',
700: 'hsl(156, 73%, 74%)',
800: 'hsl(154, 75%, 87%)',
900: 'hsl(152, 68%, 96%)'
},
redditRed: '#FF4500',
redditNav: '#1A1A1B',
redditSearch: '#272729',
redditBG: '#141415'
},
keyframes: {
wiggle: {
'0%, 100%': { transform: 'rotate(-3deg)' },
'50%': { transform: 'rotate(3deg)' }
},
hero: {
transform: 'translate3d(0px, 0px, 0px)'
}
},
animation: {
wiggle: 'wiggle 10s ease-in-out infinite',
hero: 'hero 1s ease-in-out infinite',
slowPing: 'pulse 10s cubic-bezier(0, 0, 0.2, 1) infinite'
},
width: {
82: '20.5rem',
100: '25rem',
200: '50rem',
'8xl': '96rem'
},
height: {
75: '75vh'
},
spacing: {
7: '1.75rem',
14: '3.5rem',
18: '4.5rem',
25: '6.25rem',
26: '6.5rem',
28: '7rem',
44: '11rem',
82: '20.5rem',
100: '25rem',
104: '26rem',
156: '39rem'
},
boxShadow: {
'outline-2': '0 0 0 2px var(--accents-0)',
magical:
'rgba(0, 0, 0, 0.02) 0px 30px 30px, rgba(0, 0, 0, 0.03) 0px 0px 8px, rgba(0, 0, 0, 0.05) 0px 1px 0px',
cardHover:
'0 4px 4.1px rgba(0, 0, 0, 0.012),0 4.9px 5.8px rgba(0, 0, 0, 0.018),0 6.3px 8.4px rgba(0, 0, 0, 0.029),0 8.8px 12.9px rgba(0, 0, 0, 0.05),0 15px 23px rgba(0, 0, 0, 0.11)'
}
},
variants: {
padding: [
'responsive',
'group-hover',
'hover',
'focus',
'even',
'odd',
'first',
'last'
],
textColor: [
'responsive',
'group-hover',
'hover',
'focus',
'even',
'first',
'last',
'odd'
],
backgroundColor: [
'responsive',
'group-hover',
'hover',
'focus',
'even',
'first',
'last',
'odd'
],
display: ['responsive', 'hover', 'group-hover'],
visibility: ['responsive', 'hover', 'group-hover'],
transitionDuration: ['responsive', 'hover', 'group-hover'],
gridColumn: ['responsive', 'hover', 'first', 'odd', 'even'],
extend: {
ringWidth: [
'responsive',
'hover',
'active',
'focus',
'group-hover'
],
ringColor: [
'responsive',
'hover',
'active',
'focus',
'group-hover'
],
fontSize: ['responsive', 'last', 'first', 'hover', 'focus'],
stroke: ['responsive', 'hover', 'focus', 'group-hover'],
fill: ['responsive', 'hover', 'focus', 'group-hover'],
gridTemplateColumns: [
'responsive',
'last',
'first',
'hover',
'focus'
],
animation: [
'responsive',
'hover',
'focus',
'motion-safe',
'motion-reduce'
],
transitionProperty: [
'responsive',
'hover',
'focus',
'motion-safe',
'motion-reduce'
],
transitionDuration: ['responsive', 'hover', 'focus'],
transitionTimingFunction: ['responsive', 'hover', 'focus'],
transitionDelay: ['responsive', 'hover', 'focus'],
scale: [
'responsive',
'hover',
'focus',
'active',
'group-hover'
],
rotate: [
'responsive',
'hover',
'focus',
'active',
'group-hover'
]
}
}
},
plugins: [
require('tailwindcss-line-clamp'),
require('@tailwindcss/typography'),
require('@tailwindcss/forms'),
require('@tailwindcss/aspect-ratio')
]
};
Run Code Online (Sandbox Code Playgroud)
如果您想知道为什么我postcss-import之前tailwindcss在 postcss.config.js 中使用该包,这是为了分离关注点和更清晰的代码。styles我有一个包含index.css、base.css、utilities.css、components.css和的顶级目录chrome-bug.css。它们的内容如下:
index.css
@import 'tailwindcss/base';
@import './base.css';
@import 'tailwindcss/components';
@import './components.css';
@import 'tailwindcss/utilities';
@import './utilities.css';
Run Code Online (Sandbox Code Playgroud)
components.css
.fit {
min-height: calc(100vh - 88px);
}
Run Code Online (Sandbox Code Playgroud)
utilities.css
#tsparticles {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
margin: 0;
}
.skeleton {
display: block;
width: 100%;
border-radius: 5px;
background-image: linear-gradient(
270deg,
var(--accents-1),
var(--accents-2),
var(--accents-2),
var(--accents-1)
);
background-size: 400% 100%;
animation: loading 8s ease-in-out infinite;
}
@keyframes loading {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
Run Code Online (Sandbox Code Playgroud)
base.css
#__next {
display: flex;
flex-direction: column;
min-height: 100vh;
}
:root {
--reddit-0: hsl(240, 2%, 8%);
--reddit-1: hsl(240, 2%, 10%);
--reddit-2: hsl(240, 3%, 16%);
--reddit-3: hsl(16, 100%, 50%);
--primary-0: hsl(209, 61%, 16%);
--primary-1: hsl(211, 39%, 23%);
--primary-2: hsl(209, 34%, 30%);
--primary-3: hsl(209, 28%, 39%);
--primary-4: hsl(210, 22%, 49%);
--primary-5: hsl(209, 23%, 60%);
--primary-6: hsl(211, 27%, 70%);
--primary-7: hsl(210, 31%, 80%);
--primary-8: hsl(212, 33%, 89%);
--primary-9: hsl(210, 36%, 96%);
--secondary-0: #d7be69;
--secondary-1: #486581;
--secondary-2: #9fb3c8;
--accents-0: hsl(195, 7%, 11%);
--accents-1: hsl(140, 2%, 26%);
--accents-2: hsl(0, 0%, 49%);
--accents-3: hsl(0, 0%, 64%);
--accents-4: hsl(0, 1%, 81%);
--accents-5: hsl(0, 0%, 89%);
--accents-6: hsl(50, 21%, 95%);
--theme-0: hsl(210, 24%, 84%);
--theme-1: hsl(209, 28%, 39%);
@apply overflow-x-hidden;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
/* Remove Safari input shadow on mobile */
textarea,
input:matches([type='email'], [type='number'], [type='password'], [type='search'], [type='tel'], [type='text'], [type='url']) {
-webkit-appearance: none;
}
html {
height: 100%;
box-sizing: border-box;
touch-action: manipulation;
font-feature-settings: 'case' 1, 'rlig' 1, 'calt' 0;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-webkit-tap-highlight-color: transparent;
-moz-osx-font-smoothing: grayscale;
--webkit-text-size-adjust: none;
text-size-adjust: none;
scroll-behavior: smooth;
}
html,
body {
font-family: var(--font-sans);
text-rendering: optimizeLegibility;
::--webkit-font-smoothing: antialiased;
::--moz-osx-font-smoothing: grayscale;
background-color: var(--reddit-0);
color: var(--text-accents-6);
}
body {
position: relative;
min-height: 100%;
margin: 0;
scrollbar-width: none;
scrollbar-color: var(--primary-0) var(--primary-9); /* scroll thumb and track */
}
body::-webkit-scrollbar {
display: thin; /* Hide scrollbar for Chrome, Safari and Opera https://www.w3schools.com/howto/howto_css_hide_scrollbars.asp */
width: 10px;
}
body::-webkit-scrollbar-track {
background: var(--accents-7); /* color of the tracking area */
}
body::-webkit-scrollbar-thumb {
background-color: var(
--secondary-0
); /* color of the scroll thumb */
border-radius: 0px; /* roundness of the scroll thumb */
border: 3px var(--secondary-0); /* creates padding around scroll thumb */
}
a {
-webkit-tap-highlight-color: hsla(0, 0%, 0%, 0);
}
.animated {
--webkit-animation-duration: 1s;
--animation-duration: 1s;
-animation-duration: 1s;
--webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
.fadeIn {
-webkit-animation-name: fadeIn;
animation-name: fadeIn;
}
@-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
Run Code Online (Sandbox Code Playgroud)
chrome-bug.css
/**
* Chrome has a bug with transitions onLoad since 2012!
*
* To prevent a "pop" of content, you have to disable all transitions until
* the page is done loading.
*
* https://lab.laukstein.com/bug/input
* https://twitter.com/timer150/status/1345217126680899584
*/
body.loading * {
transition: none !important;
}
Run Code Online (Sandbox Code Playgroud)
chrome-bug 类通过useEffect挂钩进行有条件处理_app.tsx,并在 的主体中调用_document.tsx
_app.tsx
import '@/styles/index.css';
import '@/styles/chrome-bug.css';
import 'keen-slider/keen-slider.min.css';
import App, {
AppContext,
AppInitialProps,
AppProps,
NextWebVitalsMetric
} from 'next/app';
import { useRouter } from 'next/router';
import { ApolloProvider } from '@apollo/client';
import { useEffect, FC } from 'react';
import {
useApollo,
initializeApollo,
addApolloState
} from '@/lib/apollo';
import * as gtag from '@/lib/analytics';
import { MediaContextProvider } from '@/lib/artsy-fresnel';
import { Head } from '@/components/Head';
import { GTagPageview } from '@/types/analytics';
// import { AppLayout } from '@/components/Layout';
import {
DynamicNavQuery,
DynamicNavQueryVariables,
DynamicNavDocument,
MenuNodeIdTypeEnum
} from '@/graphql/generated/graphql';
const Noop: FC = ({ children }) => <>{children}</>;
function NextApp({
Component,
pageProps: { ...pageProps }
}: AppProps<typeof NextApp.getInitialProps>) {
const apolloClient = useApollo(pageProps);
const LayoutNoop = (Component as any).LayoutNoop || Noop;
const router = useRouter();
useEffect(() => {
document.body.classList?.remove('loading');
}, []);
useEffect(() => {
const handleRouteChange = (url: GTagPageview) => {
gtag.pageview(url);
};
router.events.on('routeChangeComplete', handleRouteChange);
return () => {
router.events.off('routeChangeComplete', handleRouteChange);
};
}, [router.events]);
return (
<>
<Head />
<ApolloProvider client={apolloClient}>
<MediaContextProvider>
<LayoutNoop pageProps={pageProps}>
<Component {...pageProps} />
</LayoutNoop>
</MediaContextProvider>
</ApolloProvider>
</>
);
}
NextApp.getInitialProps = async (
appContext: AppContext
): Promise<AppInitialProps> => {
const pageProps = await App.getInitialProps(appContext);
const graphqlClient = initializeApollo();
const dynamicNav = await graphqlClient.query<
DynamicNavQuery,
DynamicNavQueryVariables
>({
query: DynamicNavDocument,
variables: {
idHead: 'Header',
idTypeHead: MenuNodeIdTypeEnum.Name,
idFoot: 'Footer',
idTypeFoot: MenuNodeIdTypeEnum.Name
}
});
| 归档时间: |
|
| 查看次数: |
2280 次 |
| 最近记录: |