25
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

初めまして。最近昼夜逆転してきた yakiniku0220です。

今回は前回書いた記事の続編で、実際にVS Codeの拡張機能の開発でも採用しているTailwind CSSの導入に関して執筆しようと思いました。
前回の記事を読んでいない方はぜひ読んでいただけると幸いです。

VS CodeのセットアップやReact.jsの導入はこの記事では省きます。

Tailwind CSSのSetup

今回はTailwind CLIを使用した手順を記載します。

Tailwind CSSのInstall

まずはTailwind CSSをinstallしてtailwind.config.jsファイルを生成します。

npm install -D tailwindcss
npx tailwindcss init

tailwind.config.jsにテンプレートファイルのパスを追記

先ほど生成したtailwind.config.jsにテンプレートファイルのパスを追記ます。
今回はdist配下のファイルをcontentに指定します。

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./dist/**/*.js"],
  theme: {
    extend: {},
  },
  plugins: [],
}

CSSにTailwindディレクティブを追加

今回はsrc配下にindex.cssというファイルを作成し、以下のコードを記載します。

@tailwind base;
@tailwind components;
@tailwind utilities;

Webpackの設定

対象のパッケージをinstallする

まずは以下のパッケージをinstallします。

yarn add -D css-minimizer-webpack-plugin mini-css-extract-plugin css-loader postcss-loader postcss autoprefixer

postcss.config.jsファイルを作成する

src配下にpostcss.config.jsファイルを作成して以下のコードを追記します。

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

webpack.config.jsファイルを編集する

次にwebpack.config.jsファイルに先ほどinstallしたpackageの設定を記載していきます。

//@ts-check

"use strict";

const path = require("path");
const webpack = require("webpack");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

//@ts-check
/** @typedef {import('webpack').Configuration} WebpackConfig **/

/** @type WebpackConfig */
const baseConfig = {
  target: "node", // VS Code extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
  mode: "none", // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
  resolve: {
    // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
    extensions: [".ts", ".js", ".tsx"],
  },
  plugins: [
    new webpack.DefinePlugin({
      "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
    }),
    new MiniCssExtractPlugin({ // MiniCssExtractPluginを追記
      filename: "./src/index.css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: "ts-loader",
          },
        ],
      },
      {
        test: /\.css$/i, // CSSファイルを別ファイルに抽出するために追加
        use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader"],
      },
    ],
  },
  optimization: { // optimization.minimizerを追加
    minimizer: [new CssMinimizerPlugin()],
  },
  devtool: "nosources-source-map",
  infrastructureLogging: {
    level: "log", // enables logging required for problem matchers
  },
};

/** @type WebpackConfig */
const extensionConfig = {
  ...baseConfig,
  entry: "./src/extension.ts", // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
  output: {
    // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
    path: path.resolve(__dirname, "dist"),
    filename: "extension.js",
    libraryTarget: "commonjs2",
  },
  externals: {
    vscode: "commonjs vscode", // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
    // modules added here also need to be added in the .vscodeignore file
  },
};

/** @type WebpackConfig */
const webviewConfig = {
  ...baseConfig,
  target: ["web", "es2020"],
  entry: "./src/index.tsx",
  experiments: { outputModule: true },
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "webview.js",
    libraryTarget: "module",
    chunkFormat: "module",
  },
};

/** @type WebpackConfig */
const styleConfig = { // index.cssをcompileするために処理を追加
  ...baseConfig,
  entry: "./src/index.css",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "index.css",
  },
};

module.exports = [extensionConfig, webviewConfig, styleConfig];

extension.tsファイルを編集する

最後にextension.tsファイルを編集します。
compileした際にdistディレクトリにindex.cssファイルが生成されるので、React.jsを導入したときに作成したgetUri関数を使用します。

// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from "vscode";

export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand("react.start", () => {
      // Create and show panel
      const panel = vscode.window.createWebviewPanel(
        "react",
        "React Sample",
        vscode.ViewColumn.One,
        {
          localResourceRoots: [
            vscode.Uri.joinPath(context.extensionUri, "dist"),
          ],
          enableScripts: true,
        }
      );

      // And set its HTML content
      panel.webview.html = getWebviewContent(
        panel.webview,
        context.extensionUri
      );
    })
  );
}

// This method is called when your extension is deactivated
export function deactivate() {}

function getUri(
  webview: vscode.Webview,
  extensionUri: vscode.Uri,
  pathList: string[]
) {
  return webview.asWebviewUri(vscode.Uri.joinPath(extensionUri, ...pathList));
}

function getNonce() {
  let text = "";
  const possible =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  for (let i = 0; i < 32; i++) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }
  return text;
}

function getWebviewContent(webview: vscode.Webview, extensionUri: vscode.Uri) {
  const webviewUri = getUri(webview, extensionUri, ["dist", "webview.js"]);
  const styleUri = getUri(webview, extensionUri, ["dist", "src", "index.css"]);

  const nonce = getNonce();

  return `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cat Coding</title>
    <link href="${styleUri}" rel="stylesheet">
</head>
<body>
  <div id="app"></div>
  <script type="module" nonce="${nonce}" src="${webviewUri}"></script>
</body>
</html>`;
}

動作確認

index.tsxファイルにTailwind CSSを書いて確認してみます。
スクリーンショット 2024-06-26 6.50.26.png

compile後、ちゃんとTailwind CSSが適用されているのが確認できました。

まとめ

今回VS Codeの拡張機能開発にTailwind CSSを入れてみました。
Tailwind CSSは個人開発でちょくちょく使っているので、個人的には開発体験は上がった気がします。
今回作ったサンプルコードは以下のリポジトリに作ってあります。
https://github.com/ebarakazuhiro/sample-vscode-extension

最後に

株式会社HRBrainでは新しいメンバーを募集中です。
興味がある方は下記のリンクから宜しくお願い致します。

25
16
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?