• How to Pipe Python stdout with xargs

    When writing instructions for getting started with Tanzawa, users needed a way to set a unique SECRET_KEY in their environment variable configuration file. Initially I had a secret key entry in the sample file with some instructions to "just modify it". But that felt like I was just passing the buck.

    What I wanted to do was to generate a unique secret_key and output it to the .env file. Outputting just the secret key is simple, you can just use >> and append output to an existing file. But I wanted to use my Python secret key output as an argument to another command.

    I did it as follows:

    python3 -c "import secrets; print(secrets.token_urlsafe())" | xargs -I{} -n1 echo SECRET_KEY={} >> .env

    1. Use the Python secrets module to generate a secure token.
    2. Pipe the output to xargs.
    3. -I is "replace string" and "{}" is the string we want xargs to replace. -n1 limits us to a single argument.
    4. xargs executes and takes our Python output as an argument and replaces the {} with it, giving us our desired string.

    Writing this now, I probably could have just used Python to include the SECRET_KEY= bit and forgone using xargs, but it was good practice anyways.
  • How to Process Tailwind / PostCSS with Webpack

    Usually when I work with webpack another tool I'm using generates the appropriate config for me and I can remain blissfully unaware of how it all works.

    With Tanzawa I've only been adding tooling when absolutely necessary. The other day I configured PostCSS and Tailwind with Webpack. It still required a bunch of searching and piecing together blog posts to get something that worked for me.

    Below is a list of facts that helped me figure out how to think about processing CSS with webpack.

    • As wrong as it feels, your entry point for processing your CSS should be a Javascript file.
    • Webpack by default does not output a separate stylesheet file. In order to output a plain CSS file, you must use the MiniCssExtractPlugin.
    • Despite wanting to output only CSS, and specifying the filename in the options (style.css), Webpack will create an empty Javascript file regardless. There isn't a way to prevent this unless you add another plugin. I'm adding it to .gitignore.
    • The "use" plugins have the following roles
      • MiniCssExtractPlugin: Exact built css to a dedicated css file.
      • css-loader: Allow you to import css from your entrypoint Javascript file
      • postcss-loader: Run postcss with yourΒ 

    // webpack.config.js
    const path = require('path');
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    
    const tailwindConfig = {
      entry: "./css/index.js",
      output: {
        path: path.resolve(__dirname, "../static/tailwind/"),
      },
      plugins: [
        new MiniCssExtractPlugin({ 
            filename: "style.css"
        }),
      ],
      module: {
       rules: [
        {
          test: /\.css$/,
            use: [
              MiniCssExtractPlugin.loader,
              { loader: "css-loader", options: { importLoaders: 1 } },
              "postcss-loader",
            ],
        },
       ],
      },
    }
    module.exports = [tailwindConfig]

    In order for postcss to play well with Tailwind and webpack, I needed to update my config to pass the tailwind plugin the path for the tailwind.config.js. It simply imports (requires) the tailwind config and immediately passes the path.

    // postcss.config.js
    module.exports = {
      plugins: [
        require("tailwindcss")("./tailwind.config.js"),
        require("autoprefixer"),
      ]
    }

    Finally to run this all for production, I execute via webpack as follows. I still need to figure out how to get the NODE_ENV environment variable set via with the webpack --production flag, so for now it's a bit redundant.

    // package.json
    {
      ...
      "scripts": {
        "build": "NODE_ENV=production webpack --mode=production"
      }
      ...
    }