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 CSS hot-reloading #2050

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open

Add CSS hot-reloading #2050

wants to merge 15 commits into from

Conversation

andrewleith
Copy link
Member

@andrewleith andrewleith commented Jan 17, 2025

Summary | Résumé

This PR updates our frontend build pipeline so that we can take better control of it. In particular, these changes enable us to implement better developer experience by allows us to generate our tailwind + css on the fly as we are developing in a few seconds, vs. waiting the 25s+ it was taking before to run npm run tailwind

Improvements

  • New npm script to watch for changes and rebuild CSS (npm run watch) 🎉
  • Updated makefile command to do this automatically when you use make run-dev 🎉
  • Smaller bundled CSS size 🎉
  • Increased productivity for frontend tasks 🎉 🎉

Build pipeline before

    graph LR
    
    subgraph js[Webpack / JS Pipeline]
        direction TB
        J0[style-loader: extract CSS from JS]
        J0 --> J1[babel-loader: Convert ES6+ to ES5]
        J1 --> J2[minification: Compress JS]
    end

    subgraph css[Webpack / CSS Pipeline]
        direction TB
        P0[css-loader: handles css imports]
        P0-->P1[style-loader: takes CSS from css-loader and injects into page]
        P1-->P2[postcss-loader: calls postcss]
        P2 --> P3[MiniCssExtractPlugin: Extract to .css file]
    end

    subgraph postcss[PostCSS]
        direction TB
        PC2[postcss-import: Combine @import files]
        PC2 --> PC3[tailwindcss: Generate utility classes]
        PC3 --> PCN[cssnano: minify css]
        PCN --> PC4[autoprefixer: Add vendor prefixes]
        PC4 --> PC5[purgecss: Remove unused CSS]
    end
    

    subgraph Gulp[Gulp]
        CB[Compile] --> CSS
        CB --> JavaScript
        CB --> Assets
        
        subgraph Assets
            direction TB
            E1[Copy Images] --> E2
            E2[Copy Fonts] --> E3
            E3[Copy Gov Assets]
        end
        
        subgraph JavaScript
            direction TB
            D1[Concatenate] --> D2
            D2[Minify] --> D3
            D3[Source Maps]
        end
        
        subgraph CSS
            direction TB
            C3[Minify]
        end
    end
    js --> css --> postcss --> Gulp
Loading

Build pipeline after

graph LR
    subgraph tw[Tailwind]
        direction TB
        TW1[Compile CSS @imports]
        TW1 --> TW2[Remove unused CSS]
        TW2 --> TW3[Minify CSS]
    end

    subgraph js[Webpack / JS Pipeline]
        direction TB
        J0[style-loader: extract CSS from JS]
        J0 --> J1[babel-loader: Convert ES6+ to ES5]
        J1 --> J2[minification: Compress JS]
    end

    subgraph Gulp[Gulp]
        
        
        subgraph Assets
            direction TB
            E1[Copy Images] --> E2
            E2[Copy Fonts] --> E3
            E3[Copy Gov Assets]
        end
        
        subgraph JavaScript - all.min.js
            direction TB
            D1[Concatenate most internal js files] --> D2
            D2[Babel plugin] --> D3
            D3[Concatenate js from libs we depend on] --> D4
            D4[Minify] --> D5
            D5[Output to /static/javascripts/all.min.js]
        end
        
        subgraph JavaScript - indiviual components
            direction TB
            JS2[Babel plugin] --> JS4
            JS4[Minify using Uglify] --> JS5
            JS5[Output invidual files to /static/javascripts]
        end
        
        subgraph CSS
            direction TB
            C1[Minify using cleanCSS] --> C3
            C3[Output to /static/stylesheets/index.css]
        end
    end
    tw --> js --> Gulp
Loading

Quick launch of notify for debugging

  • Use the following tasks.json (put it in .vscode/)
  • In VSCode, press cmd+shift+p, type run task
  • Select Dev environment, press enter

This will launch flask, tailwind to watch your css, and attach the debugger.

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Dev Environment",
      "dependsOrder": "parallel",
      "dependsOn": [ "Watch Tailwind", "Run Flask Debug", "Attach Debugger"],
      "group": {
        "kind": "build",
        "isDefault": true
      }
    },
    {
      "label": "Watch Tailwind",
      "type": "shell",
      "command": "npm run watch",
      "problemMatcher": [],
      "presentation": {
        "group": "groupA",
        "panel": "new"
      }
    },
    {
        "label": "Run Flask Debug",
        "type": "shell",
        "command": "FLASK_DEBUG=1 poetry run python -m debugpy --listen localhost:5678 -m flask run -p 6012 --host=localhost",
        "isBackground": true,
        "problemMatcher": {
            "pattern": {
                "regexp": "Debug mode: on",
                "file": 1,
                "line": 1,
                "column": 1,
                "message": 1
            },
            "background": {
                "activeOnStart": true,
                "beginsPattern": "Serving Flask app",
                "endsPattern": "Debug mode: on"
            }
        },
        "presentation": {
            "group": "groupA",
            "panel": "new"
        }
    },
    {
      "label": "Attach Debugger",
      "type": "process",
      "command": "${command:workbench.action.debug.start}",
      "dependsOn": ["Run Flask Debug"],
      "args": ["Python: Remote Attach"],
      "problemMatcher": []
    }
  ]
}

Test instructions | Instructions pour tester la modification

Sequential steps (1., 2., 3., ...) that describe how to test this change. This
will help a developer test things out without too much detective work. Also,
include any environmental setup steps that aren't in the normal README steps
and/or any time-based elements that this requires.


Étapes consécutives (1., 2., 3., …) qui décrivent la façon de tester la
modification. Elles aideront les développeurs à faire des tests sans avoir à
jouer au détective. Veuillez aussi inclure toutes les étapes de configuration
de l’environnement qui ne font pas partie des étapes normales dans le fichier
README et tout élément temporel requis.

Copy link

@andrewleith andrewleith marked this pull request as ready for review January 20, 2025 19:26
Comment on lines +170 to 171
<script nonce="{{ request_nonce }}" type="text/javascript" src="{{ asset_url('javascripts/index.min.js') }}"></script>
<script nonce="{{ request_nonce }}" type="text/javascript" src="{{ asset_url('javascripts/all.min.js') }}"></script>
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to load both "index" and "all"? It seems like we prepend all with index in gulpfile.

Copy link
Member Author

Choose a reason for hiding this comment

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

We dont combine them - but i have no idea why. I think we probably could just have the one.

Comment on lines +102 to +106
paths.src + "javascripts/branding_request.js",
paths.src + "javascripts/formValidateRequired.js",
paths.src + "javascripts/sessionRedirect.js",
paths.src + "javascripts/touDialog.js",
paths.src + "javascripts/templateFilters.js"
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these ever bundled? Do we load them piece by piece in our html templates? If not, we could remove this step?

Copy link
Member Author

Choose a reason for hiding this comment

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

These few are not bundled. The thought when they were created was that since they are not often used, they could exist separately. Although, the templateFilters one probably should be bundled now that I look more closely.

@@ -9,9 +9,9 @@
"test": "jest --config tests/javascripts/jest.config.js tests/javascripts",
"webpack": "webpack --config webpack.config.js",
"build": "gulp",
"watch": "gulp watch",
"watch": "npx tailwindcss -i ./app/assets/stylesheets/tailwind/style.css -o ./app/static/stylesheets/index.css --watch ",
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need gulp in there?

Copy link
Member Author

Choose a reason for hiding this comment

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

Nope - all the css is within styles.css now and we shouldnt add arbitrary css to gulp anymore.

Copy link
Contributor

Choose a reason for hiding this comment

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

So watch will only update on css changes, and not script changes?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah - I didnt tackle watching the js - could be another PR!

sessionRedirect: ["./app/assets/javascripts/sessionRedirect.js"],
touDialog: ["./app/assets/javascripts/touDialog.js"],
templateFilters: ["./app/assets/javascripts/templateFilters.js"],
index: ["./app/assets/javascripts/index.js"],
Copy link
Contributor

Choose a reason for hiding this comment

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

lovely

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah this file being named main.js but having a source of index.js when we ALREADY HAVE a file named main.js was just so super confusing.

This is still confusing - but less so :D

Comment on lines -47 to -57
{
test: /\.css$/i,
include: [
path.resolve(__dirname, "app/assets/stylesheets/tailwind")
],
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader"
]
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Good riddance!

@andrewleith andrewleith changed the title Task/better dx Add CSS hot-reloading Jan 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants