简体   繁体   English

NextJs Tailwind 构建(清除)删除所有样式

[英]NextJs Tailwind build (purge) removes all styling

In my current NextJS project, I am using Tailwind as a CSS framework.在我当前的 NextJS 项目中,我使用 Tailwind 作为 CSS 框架。 When I run yarn dev , everything works fine, but whenever I run yarn build followed by a yarn start , all of my CSS seems to be purged as the layout of my page is completely different.当我运行yarn dev时,一切正常,但每当我运行yarn build后跟yarn start ,我的所有 CSS 似乎都被清除了,因为我的页面布局完全不同。

Before:前: 在此处输入图像描述

After:后: 在此处输入图像描述

My tailwind.config.js file:我的 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')],
};

postcss.config.js file: 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,
  ],
};

_app.tsx: _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;

globals.css:全球.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;
}

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

If there is anything that seems off, feel free to let me know.如果有任何问题,请随时告诉我。 I have looked at other issues online but did not find and solution to my problem.我在网上查看了其他问题,但没有找到并解决我的问题。

Double check the paths in tailwind.config.js .仔细检查tailwind.config.js中的路径。 If your components are not in the components directory, then you need to update the purge paths to reflect this.如果您的组件不在components目录中,那么您需要更新purge路径以反映这一点。

I think I see the issue.我想我看到了这个问题。 @fullhuman/postcss-purgecss has been bundled with tailwindcss since v1.4 or so. @fullhuman/postcss-purgecss自 v1.4 左右以来已与 tailwindcss 捆绑在一起。 Since it's manually declared in your postcss file as well, it's being executed twice which is wiping all of your styles.由于它也是在您的 postcss 文件中手动声明的,因此它被执行了两次,这将擦除您的所有 styles。 Also the fact that it only wipes your styles in production indicates that it is the culprit as execution of that particular package is dependent on process.env.NODE_ENV===production .此外,它仅在生产中擦除您的 styles 的事实表明它是罪魁祸首,因为执行特定的 package 取决于process.env.NODE_ENV===production Removing it from your postcss file should resolve your issue since it is already being executed under the hood by the tailwindcss bundle.从您的 postcss 文件中删除它应该可以解决您的问题,因为它已经由 tailwindcss 包在后台执行。

Here is my postcss with tailwindcss@2.0.3 for comparison:这是我的 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
                }
            }
        ]
    ]
};

One other possibility is that you aren't wrapping the paths/file-types targeted for purging within a top-level content object.另一种可能性是您没有将要清除的路径/文件类型包装在顶级content object 中。 From the code provided for your tailwind.config.js file:从为您的tailwind.config.js文件提供的代码中:

module.exports = {
  purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
  //...
}

Here is my tailwind.config.js for cross-comparison这是我用于交叉比较的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')
    ]
};

If you're wondering why I use the postcss-import package before tailwindcss in my postcss.config.js, it's for separation of concerns and cleaner code.如果您想知道为什么我在tailwindcss中的 tailwindcss 之前使用postcss-import package,它是为了分离关注点和更清晰的代码。 I have a top-level styles directory containing index.css , base.css , utilities.css , components.css , and chrome-bug.css . I have a top-level styles directory containing index.css , base.css , utilities.css 8CBA22E28EB17B5F5C6AE2A266AZ , components.css 8CBA22E28EB17B5F5C6AE2A266AZ , and chrome-bug.css . Their contents are as follows:它们的内容如下:

index.css

@import 'tailwindcss/base';
@import './base.css';

@import 'tailwindcss/components';
@import './components.css';

@import 'tailwindcss/utilities';
@import './utilities.css';

components.css

.fit {
    min-height: calc(100vh - 88px);
}

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

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

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

The chrome-bug class is conditionally handled via a useEffect hook in _app.tsx and is called in the body of _document.tsx chrome-bug class 通过 _app.tsx 中的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
        }
    });
    return addApolloState(graphqlClient, {
        pageProps: {
            ...pageProps.pageProps,
            Header: dynamicNav.data.Header,
            Footer: dynamicNav.data.Footer
        }
    });
};

export function reportWebVitals(metric: NextWebVitalsMetric) {
    console.debug('vital: ', metric);
}

export default NextApp;

_document.tsx

import Document, {
    Head,
    Html,
    Main,
    NextScript,
    DocumentContext
} from 'next/document';
import { mediaStyles } from '@/lib/artsy-fresnel';
const GA_TRACKING_ID = 'G-RJQZB1C7TR';

class MyDocument extends Document {
    static async getInitialProps(ctx: DocumentContext) {
        const initialProps = await Document.getInitialProps(ctx);
        return { ...initialProps };
    }
    render() {
        return (
            <Html lang='en-US'>
                <Head>
                    <meta charSet='utf-8' />
                    <link
                        rel='stylesheet'
                        href='https://rsms.me/inter/inter.css'
                    />
                    <link rel='shortcut icon' href='/assets/favicon.ico' />
                    <style
                        type='text/css'
                        dangerouslySetInnerHTML={{ __html: mediaStyles }}
                    />
                    <script
                        async
                        src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`}
                    />
                    <script
                        dangerouslySetInnerHTML={{
                            __html: `
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());

        gtag('config', '${GA_TRACKING_ID}', {
            page_path: window.location.pathname,
        });
    `
                        }}
                    />
                </Head>
                <body className='loading'>
                    <Main />
                    <NextScript />
                </body>
            </Html>
        );
    }
}

export default MyDocument;

For the sake of thoroughness, here is my package.json为了彻底起见,这里是我的package.json

{
    "name": "clean-fade",
    "version": "1.0.0",
    "main": "index.js",
    "repository": "git@gitlab.com:windy-city-devs-llc/clean-fade.git",
    "author": "Andrew Ross <andrew.simpson.ross@gmail.com>",
    "license": "MIT",
    "scripts": {
        "test": "jest",
        "test-all": "yarn lint && yarn type-check && yarn test",
        "codegen": "graphql-codegen --config codegen.yml -r dotenv/config",
        "dev": "next -p 5005",
        "prod:build": "yarn codegen && yarn build",
        "dev:debug": "cross-env NODE_OPTIONS='--inspect' next dev",
        "build": "next build",
        "analyze": "cross-env ANALYZE=true yarn build",
        "find:unused": "next-unused",
        "tsconfig:effective": "tsc --showConfig",
        "pretty:quick": "yarn pretty-quick --staged",
        "prepare": "husky install",
        "lint": "eslint . --ext ts --ext tsx --ext js",
        "format": "prettier --write .",
        "type-check": "tsc --pretty --noEmit"
    },
    "lint-staged": {
        "*.@(ts|tsx)": [
            "yarn lint",
            "yarn format"
        ]
    },
    "next-unused": {
        "alias": {
            "@/components/*": [
                "components/*"
            ],
            "@/config/*": [
                "config/*"
            ],
            "@/graphql/*": [
                "graphql/*"
            ],
            "@/lib/*": [
                "lib/*"
            ],
            "@/pages/*": [
                "pages/*"
            ],
            "@/scripts/*": [
                "scripts/*"
            ],
            "@/styles/*": [
                "styles/*"
            ],
            "@/test/*": [
                "test/*"
            ],
            "@/types/*": [
                "types/*"
            ]
        },
        "debug": true,
        "include": [
            "components",
            "lib",
            "pages"
        ],
        "exclude": [],
        "entrypoints": [
            "pages"
        ]
    },
    "dependencies": {
        "@apollo/client": "^3.3.12",
        "@artsy/fresnel": "^1.3.1",
        "@headlessui/react": "^0.3.1",
        "@reach/portal": "^0.13.2",
        "body-scroll-lock": "^3.1.5",
        "classnames": "^2.2.6",
        "date-fns": "^2.19.0",
        "graphql": "^15.5.0",
        "html-react-parser": "^1.2.4",
        "isomorphic-unfetch": "^3.1.0",
        "js-cookie": "^2.2.1",
        "keen-slider": "^5.4.0",
        "lodash.random": "^3.2.0",
        "lodash.throttle": "^4.1.1",
        "next": "^10.0.9",
        "next-seo": "^4.20.0",
        "next-themes": "^0.0.12",
        "preact": "^10.5.13",
        "react": "^17.0.1",
        "react-dom": "^17.0.1",
        "react-intersection-observer": "^8.31.0",
        "react-markdown": "^5.0.3",
        "react-merge-refs": "^1.1.0",
        "react-tsparticles": "^1.20.1",
        "remark-gfm": "^1.0.0",
        "swr": "^0.5.3",
        "tabbable": "^5.1.6"
    },
    "devDependencies": {
        "@babel/core": "^7.13.10",
        "@graphql-codegen/cli": "^1.21.3",
        "@graphql-codegen/import-types-preset": "^1.18.1",
        "@graphql-codegen/introspection": "^1.18.1",
        "@graphql-codegen/near-operation-file-preset": "^1.17.13",
        "@graphql-codegen/schema-ast": "^1.18.1",
        "@graphql-codegen/typescript": "^1.21.1",
        "@graphql-codegen/typescript-operations": "^1.17.15",
        "@graphql-codegen/typescript-react-apollo": "2.1.1",
        "@next/bundle-analyzer": "^10.0.9",
        "@tailwindcss/aspect-ratio": "^0.2.0",
        "@tailwindcss/forms": "^0.2.1",
        "@tailwindcss/typography": "^0.4.0",
        "@testing-library/dom": "^7.30.0",
        "@testing-library/jest-dom": "^5.11.9",
        "@testing-library/react": "^11.2.5",
        "@testing-library/user-event": "^12.8.3",
        "@types/body-scroll-lock": "^2.6.1",
        "@types/classnames": "^2.2.11",
        "@types/gtag.js": "^0.0.4",
        "@types/jest": "^26.0.20",
        "@types/js-cookie": "^2.2.6",
        "@types/lodash.random": "^3.2.6",
        "@types/lodash.throttle": "^4.1.6",
        "@types/node": "^14.14.35",
        "@types/react": "^17.0.3",
        "@types/react-dom": "^17.0.2",
        "@types/react-test-renderer": "^17.0.1",
        "@types/tabbable": "^3.1.0",
        "@typescript-eslint/eslint-plugin": "^4.18.0",
        "@typescript-eslint/parser": "^4.18.0",
        "autoprefixer": "^10.2.5",
        "babel-jest": "^26.6.3",
        "cross-env": "^7.0.3",
        "dotenv": "^8.2.0",
        "dotenv-cli": "^4.0.0",
        "eslint": "^7.22.0",
        "eslint-config-prettier": "^8.1.0",
        "eslint-plugin-react": "^7.22.0",
        "globby": "^11.0.2",
        "husky": "^5.1.3",
        "identity-obj-proxy": "^3.0.0",
        "jest": "^26.6.3",
        "jest-watch-typeahead": "^0.6.1",
        "lint-staged": "^10.5.4",
        "next-page-tester": "^0.24.0",
        "next-unused": "^0.0.3",
        "postcss": "^8.2.8",
        "postcss-flexbugs-fixes": "^5.0.2",
        "postcss-import": "^14.0.0",
        "postcss-preset-env": "^6.7.0",
        "postinstall-postinstall": "^2.1.0",
        "prettier": "^2.2.1",
        "pretty-quick": "^3.1.0",
        "react-test-renderer": "^17.0.1",
        "stylelint": "^13.12.0",
        "stylelint-config-recommended": "^4.0.0",
        "tailwindcss": "^2.0.3",
        "tailwindcss-line-clamp": "^1.0.5",
        "ts-jest": "^26.5.3",
        "typescript": "^4.2.3",
        "yaml-loader": "^0.6.0"
    }
}

Next.js, How to setup tailwindcss with purge css to remove unused css Next.js,如何使用清除设置 tailwindcss css 以删除未使用的 css

  1. install tailwindcss安装 tailwindcss
yarn add -D tailwindcss
npx tailwindcss init
  1. configure your tailwind.config.js配置你的 tailwind.config.js
module.exports = {
    content: [
        './pages/**/*.{js,jsx,ts,tsx}',
        './components/**/*.{js,jsx,ts,tsx}'
    ],
    theme: {
        extend: {},
    },
    plugins: [],
}
  1. install purge css plugins安装清除 css 插件
yarn add @fullhuman/postcss-purgecss postcss-preset-env
  1. configure postcss.config.js配置 postcss.config.js
module.exports = {
    plugins: {
        tailwindcss: {},
        autoprefixer: {},
        '@fullhuman/postcss-purgecss': {
            content: [
                './pages/**/*.{js,jsx,ts,tsx}',
                './components/**/*.{js,jsx,ts,tsx}'
            ],
            defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || []
        },
        'postcss-preset-env': {}
    },
}

After that try adding a classname that you intentionally won't use and try to build for production and test from coverage tab that this classname is not loaded within source file之后尝试添加一个您故意不使用的类名,并尝试从覆盖选项卡构建生产和测试该类名未加载到源文件中

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM