Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Purgecss to with-tailwindcss example #9145

Merged
merged 8 commits into from
Oct 23, 2019
Merged

Add Purgecss to with-tailwindcss example #9145

merged 8 commits into from
Oct 23, 2019

Conversation

taylorbryant
Copy link
Contributor

@taylorbryant taylorbryant commented Oct 21, 2019

By default, Tailwind CSS generates a stylesheet that’s 477.6kb. To combat the large file size, Tailwind CSS recommends using Purgecss.

This PR:

  • Closes add purge css in tailwind css example #9142
  • Pulls in @fullhuman/postcss-purgecss as a dependency
  • Adds Purgecss to the list of PostCSS plugins and incorporates an extractor that's compatible with Tailwind CSS
  • Wraps the Tailwind CSS base styles in a comment to prevent purging
  • Improves the README and addresses limitations caused by Purgecss
  • Adds cssnano to the list of PostCSS plugins; it's in the package.json, but it wasn't being used
@ijjk
Copy link
Member

ijjk commented Oct 21, 2019

Stats from current PR

Default Server Mode
General
zeit/next.js canary taylorbryant/next.js canary Change
buildDuration 15.9s 15.8s -63ms
nodeModulesSize 48.5 MB 48.5 MB
Client Bundles (main, webpack, commons)
zeit/next.js canary taylorbryant/next.js canary Change
main-HASH.js 18.9 kB 18.9 kB
main-HASH.js gzip 6.79 kB 6.79 kB
webpack-HASH.js 1.53 kB 1.53 kB
webpack-HASH.js gzip 746 B 746 B
16b1a7225520..4a7b46563.js 14.9 kB 14.9 kB
16b1a7225520..6563.js gzip 5.38 kB 5.38 kB
4952ddcd88e7..bfe360fe6.js 10.5 kB 10.5 kB
4952ddcd88e7..0fe6.js gzip 4.06 kB 4.06 kB
commons.HASH.js 11.3 kB 11.3 kB
commons.HASH.js gzip 4.23 kB 4.23 kB
de003c3a9d30..9e9c1d310.js 28.6 kB 28.6 kB
de003c3a9d30..d310.js gzip 10.8 kB 10.8 kB
framework.1b..cdcfe1283.js 125 kB 125 kB
framework.1b..1283.js gzip 39.4 kB 39.4 kB
Overall change 211 kB 211 kB
Client Bundles (main, webpack, commons) Modern
zeit/next.js canary taylorbryant/next.js canary Change
main-HASH.module.js 17.2 kB 17.2 kB
main-HASH.module.js gzip 6.52 kB 6.52 kB
webpack-HASH.module.js 1.53 kB 1.53 kB
webpack-HASH..dule.js gzip 746 B 746 B
16b1a7225520..d2.module.js 10.8 kB 10.8 kB
16b1a7225520..dule.js gzip 4.05 kB 4.05 kB
4952ddcd88e7..4a.module.js 12.8 kB 12.8 kB
4952ddcd88e7..dule.js gzip 4.75 kB 4.75 kB
de003c3a9d30..11.module.js 22.1 kB 22.1 kB
de003c3a9d30..dule.js gzip 8.68 kB 8.68 kB
framework.5b..d3.module.js 125 kB 125 kB
framework.5b..dule.js gzip 39.4 kB 39.4 kB
Overall change 190 kB 190 kB
Client Pages
zeit/next.js canary taylorbryant/next.js canary Change
_app.js 1.63 kB 1.63 kB
_app.js gzip 788 B 788 B
_error.js 12.3 kB 12.3 kB
_error.js gzip 4.79 kB 4.79 kB
hooks.js 1.51 kB 1.51 kB
hooks.js gzip 789 B 789 B
index.js 318 B 318 B
index.js gzip 222 B 222 B
link.js 8.15 kB 8.15 kB
link.js gzip 3.5 kB 3.5 kB
routerDirect.js 413 B 413 B
routerDirect.js gzip 285 B 285 B
withRouter.js 423 B 423 B
withRouter.js gzip 284 B 284 B
Overall change 24.7 kB 24.7 kB
Client Pages Modern
zeit/next.js canary taylorbryant/next.js canary Change
_app.module.js 1.54 kB 1.54 kB
_app.module.js gzip 756 B 756 B
_error.module.js 10.6 kB 10.6 kB
_error.module.js gzip 4.28 kB 4.28 kB
hooks.module.js 1.52 kB 1.52 kB
hooks.module.js gzip 794 B 794 B
index.module.js 294 B 294 B
index.module.js gzip 223 B 223 B
link.module.js 8.53 kB 8.53 kB
link.module.js gzip 3.69 kB 3.69 kB
routerDirect.module.js 399 B 399 B
routerDirect..dule.js gzip 285 B 285 B
withRouter.module.js 409 B 409 B
withRouter.m..dule.js gzip 282 B 282 B
Overall change 23.3 kB 23.3 kB
Client Build Manifests
zeit/next.js canary taylorbryant/next.js canary Change
_buildManifest.js 244 B 244 B
_buildManifest.js gzip 200 B 200 B
_buildManifest.module.js 251 B 251 B
_buildManife..dule.js gzip 209 B 209 B
Overall change 495 B 495 B
Rendered Page Sizes
zeit/next.js canary taylorbryant/next.js canary Change
index.html 3.94 kB 3.94 kB
index.html gzip 1 kB 1 kB
link.html 4.47 kB 4.47 kB
link.html gzip 1.08 kB 1.08 kB
withRouter.html 4.47 kB 4.47 kB
withRouter.html gzip 1.07 kB 1.07 kB
Overall change 12.9 kB 12.9 kB

Serverless Mode
General
zeit/next.js canary taylorbryant/next.js canary Change
buildDuration 16.8s 16.5s -303ms
nodeModulesSize 48.5 MB 48.5 MB
Client Bundles (main, webpack, commons)
zeit/next.js canary taylorbryant/next.js canary Change
main-HASH.js 18.9 kB 18.9 kB
main-HASH.js gzip 6.79 kB 6.79 kB
webpack-HASH.js 1.53 kB 1.53 kB
webpack-HASH.js gzip 746 B 746 B
16b1a7225520..4a7b46563.js 14.9 kB 14.9 kB
16b1a7225520..6563.js gzip 5.38 kB 5.38 kB
4952ddcd88e7..bfe360fe6.js 10.5 kB 10.5 kB
4952ddcd88e7..0fe6.js gzip 4.06 kB 4.06 kB
commons.HASH.js 11.3 kB 11.3 kB
commons.HASH.js gzip 4.23 kB 4.23 kB
de003c3a9d30..9e9c1d310.js 28.6 kB 28.6 kB
de003c3a9d30..d310.js gzip 10.8 kB 10.8 kB
framework.1b..cdcfe1283.js 125 kB 125 kB
framework.1b..1283.js gzip 39.4 kB 39.4 kB
Overall change 211 kB 211 kB
Client Bundles (main, webpack, commons) Modern
zeit/next.js canary taylorbryant/next.js canary Change
main-HASH.module.js 17.2 kB 17.2 kB
main-HASH.module.js gzip 6.52 kB 6.52 kB
webpack-HASH.module.js 1.53 kB 1.53 kB
webpack-HASH..dule.js gzip 746 B 746 B
16b1a7225520..d2.module.js 10.8 kB 10.8 kB
16b1a7225520..dule.js gzip 4.05 kB 4.05 kB
4952ddcd88e7..4a.module.js 12.8 kB 12.8 kB
4952ddcd88e7..dule.js gzip 4.75 kB 4.75 kB
de003c3a9d30..11.module.js 22.1 kB 22.1 kB
de003c3a9d30..dule.js gzip 8.68 kB 8.68 kB
framework.5b..d3.module.js 125 kB 125 kB
framework.5b..dule.js gzip 39.4 kB 39.4 kB
Overall change 190 kB 190 kB
Client Pages
zeit/next.js canary taylorbryant/next.js canary Change
_app.js 1.63 kB 1.63 kB
_app.js gzip 788 B 788 B
_error.js 12.3 kB 12.3 kB
_error.js gzip 4.79 kB 4.79 kB
hooks.js 1.51 kB 1.51 kB
hooks.js gzip 789 B 789 B
index.js 318 B 318 B
index.js gzip 222 B 222 B
link.js 8.15 kB 8.15 kB
link.js gzip 3.5 kB 3.5 kB
routerDirect.js 413 B 413 B
routerDirect.js gzip 285 B 285 B
withRouter.js 423 B 423 B
withRouter.js gzip 284 B 284 B
Overall change 24.7 kB 24.7 kB
Client Pages Modern
zeit/next.js canary taylorbryant/next.js canary Change
_app.module.js 1.54 kB 1.54 kB
_app.module.js gzip 756 B 756 B
_error.module.js 10.6 kB 10.6 kB
_error.module.js gzip 4.28 kB 4.28 kB
hooks.module.js 1.52 kB 1.52 kB
hooks.module.js gzip 794 B 794 B
index.module.js 294 B 294 B
index.module.js gzip 223 B 223 B
link.module.js 8.53 kB 8.53 kB
link.module.js gzip 3.69 kB 3.69 kB
routerDirect.module.js 399 B 399 B
routerDirect..dule.js gzip 285 B 285 B
withRouter.module.js 409 B 409 B
withRouter.m..dule.js gzip 282 B 282 B
Overall change 23.3 kB 23.3 kB
Client Build Manifests
zeit/next.js canary taylorbryant/next.js canary Change
_buildManifest.js 244 B 244 B
_buildManifest.js gzip 200 B 200 B
_buildManifest.module.js 251 B 251 B
_buildManife..dule.js gzip 209 B 209 B
Overall change 495 B 495 B
Serverless bundles
zeit/next.js canary taylorbryant/next.js canary Change
_error.js 234 kB 234 kB
_error.js gzip 62.8 kB 62.8 kB
hooks.html 4.08 kB 4.08 kB
hooks.html gzip 1.03 kB 1.03 kB
index.js 235 kB 235 kB
index.js gzip 62.9 kB 62.9 kB
link.js 267 kB 267 kB
link.js gzip 71.9 kB 71.9 kB
routerDirect.js 260 kB 260 kB
routerDirect.js gzip 69.9 kB 69.9 kB
withRouter.js 260 kB 260 kB
withRouter.js gzip 69.8 kB 69.8 kB
Overall change 1.26 MB 1.26 MB

Commit: eccadd6

@Timer
Copy link
Member

Timer commented Oct 21, 2019

How does this work for HTML classes that are dynamically composed?

@taylorbryant
Copy link
Contributor Author

taylorbryant commented Oct 21, 2019

How does this work for HTML classes that are dynamically composed?

It won't work with dynamically composed classes. Purgecss is "dumb" and simply looks for a matching string.

Here's what the docs say about that issue:
https://tailwindcss.com/docs/controlling-file-size/#writing-purgeable-html

What do you think the best path forward is? Should I create a separate example that uses Purgecss instead of baking it into this example?

@Timer
Copy link
Member

Timer commented Oct 21, 2019

I'm OK with it being in the example as long as we explicitly call out this restriction.

Copy link
Member

@Timer Timer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@Timer Timer added this to the 9.1.2 milestone Oct 23, 2019
@Timer Timer added ready to land examples Issue/PR related to examples labels Oct 23, 2019
@Timer Timer merged commit b96f1ae into vercel:canary Oct 23, 2019
@justsee
Copy link

justsee commented Oct 24, 2019

Hi @taylorbryant, thanks for the example and PR!

One issue having just used it in familiarising myself with tailwindcss - the dependency on purgecss in development breaks auto-reloading of styles.

The docs themselves recommend only depending on it in production, (and adding it as the last dependency, though not sure why this is important): https://tailwindcss.com/docs/controlling-file-size/

// postcss.config.js
const purgecss = require('@fullhuman/postcss-purgecss')({

  // Specify the paths to all of the template files in your project 
  content: [
    './src/**/*.html',
    './src/**/*.vue',
    './src/**/*.jsx',
    // etc.
  ],

  // Include any special characters you're using in this regular expression
  defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || []
})

module.exports = {
  plugins: [
    require('tailwindcss'),
    require('autoprefixer'),
    ...process.env.NODE_ENV === 'production'
      ? [purgecss]
      : []
  ]
}

Is it possible to push a commit to this PR to merge again, or create a new one?

@justsee
Copy link

justsee commented Oct 24, 2019

I've just modified your example postcss.config.js as follows:

module.exports = ({ env }) => ({
  plugins: [
    require('postcss-easy-import'),
    require('tailwindcss'),
    require('autoprefixer'),
    require('cssnano'),
    env === 'production'
      ? require('@fullhuman/postcss-purgecss')({
        content: ['./pages/**/*.js', './components/**/*.js'],
        defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || []
      })
      : false
  ]
})
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
examples Issue/PR related to examples
4 participants