10
6

More than 1 year has passed since last update.

Web制作向けnpm-scripts 3

Last updated at Posted at 2022-09-18

ついにIEのサポートが終了したので、更新しました。
Web制作向けnpm-scripts 2
Web制作向けnpm-scripts

変更点

  • IE対応廃止(JSのバンドル、polyfili自動追加、トランスパイル)
  • webp対応(JPG、PNGもwebpに変換)
  • ESModule化

補足

  • node.js v18.7.0、npm 7.7.4で作成
  • avif対応は時期尚早のため見送り

ファイル構成

directory
 website
 ├ src
 │ ├ pug
 │ ├ img
 │ ├ scss
 │ └ ts
 ├ package.json
 ├ package-lock.json
 ├ imagemin.js
 ├ jest.config.js
 ├ tsconfig.json
 ├ .browserslistrc
 ├ .eslintrc.json 
 ├ .prettierrc.json 
 ├ .stylelintrc.json
 └ .stylelintignore 

npm-scriptsの準備

terminal
 npm init -y
 
 npm i -D npm-run-all
 npm i -D chokidar-cli

ホットリロード

Browser-Sync

インストール

terminal
 npm i -D browser-sync

npmコマンド追加

package.json
"scripts": {
  "start:server": "browser-sync start -s dist -w src/*.html src/css/*.css src/js/*.js"
}

動作確認

terminal
npm run start:server 

ブラウザが立ち上がれば成功です。
まだデータが無いのでエラーで問題ありません。
Ctrl+Cで終了します。

Pug

インストール

terminal
npm i -D github:pugjs/pug-cli#master

npmコマンド追加

package.json
"scripts": {
  "compile:pug": "pug src/pug/ --hierarchy -o dist/ -P",
  "watch:pug": "pug src/pug/ --hierarchy -o dist/ -w -P",
}

動作確認

/src/pug/配下にPugファイルを設置して、変換してみてください。
Pugの記法まとめ

terminal
//1回変換
npm run compile:pug

//Pugファイルの変更を監視して変換
npm run watch:pug

/src/pug/配下のPugファイルが/dist/配下にHTMLとして変換されれば成功です。

CSS

Sass(Dart-Sass)

SCSSファイルをCSSファイルに変換します。

インストール

terminal
npm i -D sass

autoprefixer

CSSのプロパティにベンダープレフィックスを付与します。

インストール]

terminal
npm i -D postcss-cli
npm i -D autoprefixer
npm i -D postcss

対象ブラウザの指定

設定例
.browserslistrc
defaults

設定は下記URLを参考に適宜変更してください。
browserslist

.browserslistrcで対象ブラウザを指定する

.browserslistrcに設定した対象ブラウザの確認

対象ブラウザの確認
terminal
npx browserslist

npmコマンド追加

pacjage.json
"scripts": {
  "compile:css2cssprefix": "postcss dist/css/style.css -u autoprefixer -o dist/css/style.css",
  "compile:scss2css": "sass src/scss/style.scss:dist/css/style.css --style=expanded --source-map-urls=relative",
  "compile:scss2cssprefix": "run-s compile:scss2css compile:css2cssprefix",
  "watch:scss2cssprefix": "chokidar \"src/scss/\" --command \"npm run compile:scss2cssprefix\" --initial", 
}

動作確認

/src/scss/配下にSCSSファイルを設置して、変換してみてください。

Sassの記法(SCSS構文)

terminal
//SCSSファイルをベンダープレフィックス付きでCSSに変換(1回)
npm run compile:scss2cssprefix

//SCSSファイルをベンダープレフィックス付きでCSSに変換(SCSSファイルを監視して変更される度)
npm run watch:scss2cssprefix

/src/scss/配下のSCSSファイルが/dist/css/配下にCSSファイルとして変換されれば成功です。

TypeScript

JavaScriptへの変換を行います。

インストール

terminal
npm i -D typescript

設定ファイルの準備

tsconfig.jsonを作成します。

terminal
tsc --init
tsconfig.json
{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file */

    /* Basic Options */
    // "incremental": true,                         /* Enable incremental compilation */
    "target": "ESNEXT" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
    "module": "ESnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
    // "lib": [],                                   /* Specify library files to be included in the compilation. */
    // "allowJs": true,                             /* Allow javascript files to be compiled. */
    // "checkJs": true,                             /* Report errors in .js files. */
    // "jsx": "preserve",                           /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
    // "declaration": true,                         /* Generates corresponding '.d.ts' file. */
    // "declarationMap": true,                      /* Generates a sourcemap for each corresponding '.d.ts' file. */
    "sourceMap": true,                           /* Generates corresponding '.map' file. */
    // "outFile": "./",                             /* Concatenate and emit output to single file. */
    "outDir": "./dist/js" /* Redirect output structure to the directory. */,
    "rootDir": "./src/ts"  /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
    // "composite": true,                           /* Enable project compilation */
    // "tsBuildInfoFile": "./",                     /* Specify file to store incremental compilation information */
    // "removeComments": true,                      /* Do not emit comments to output. */
    // "noEmit": true,                              /* Do not emit outputs. */
    // "importHelpers": true,                       /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,                  /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    // "isolatedModules": true,                     /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

    /* Strict Type-Checking Options */
    "strict": true /* Enable all strict type-checking options. */,
    // "noImplicitAny": true,                       /* Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,                    /* Enable strict null checks. */
    // "strictFunctionTypes": true,                 /* Enable strict checking of function types. */
    // "strictBindCallApply": true,                 /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
    // "strictPropertyInitialization": true,        /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                      /* Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                        /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    // "noUnusedLocals": true,                      /* Report errors on unused locals. */
    // "noUnusedParameters": true,                  /* Report errors on unused parameters. */
    // "noImplicitReturns": true,                   /* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,          /* Report errors for fallthrough cases in switch statement. */
    // "noUncheckedIndexedAccess": true,            /* Include 'undefined' in index signature results */
    // "noPropertyAccessFromIndexSignature": true,  /* Require undeclared properties from index signatures to use element accesses. */

    /* Module Resolution Options */
    // "moduleResolution": "node",                  /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    // "baseUrl": "./",                             /* Base directory to resolve non-absolute module names. */
    // "paths": {},                                 /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                              /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                             /* List of folders to include type definitions from. */
    // "types": [],                                 /* Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,        /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
    // "preserveSymlinks": true,                    /* Do not resolve the real path of symlinks. */
    // "allowUmdGlobalAccess": true,                /* Allow accessing UMD globals from modules. */

    /* Source Map Options */
    // "sourceRoot": "",                            /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                               /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,                     /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                       /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    // "experimentalDecorators": true,              /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,               /* Enables experimental support for emitting type metadata for decorators. */

    /* Advanced Options */
    "skipLibCheck": true /* Skip type checking of declaration files. */,
    "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
  },
  "exclude": ["node_modules"]
}

動作確認

/src/ts/index.ts
import { importTest } from "./sub";

const message = "TypeScriptの変換成功";

console.log(message);
console.log(importTest);
/src/ts/sub.ts
export const importTest: string = "sub.tsからのimport成功";
terminal
//TypeScriptファイルをJavsScriptファイルに変換
npm run compile:ts

//TypeScriptファイルをJavsScriptファイルに変換(TypeScriptファイルを監視して変更される度)
npm run watch:ts

/src/ts/配下のTypeScriptファイルが/dist/js/配下にJavsScriptファイルとして変換されれば成功です。

画像圧縮

対応するファイル形式

  • jpg
  • png
  • webp
  • gif
  • svg
    (jpgとpngはwebpに変換します)

インストール

terminal
npm i -D imagemin-cli
npm i -D imagemin-keep-folder
npm i -D imagemin-gifsicle
npm i -D imagemin-svgo
npm i -D imagemin-webp

npmコマンド追加

package.json
"scripts": {
 "watch:img": "chokidar \"src/img/**/*\" --command \"node imagemin.js\" --initial"
}

設定ファイル

imagemin.js
import keepfolder from "imagemin-keep-folder";
import gifsicle from "imagemin-gifsicle";
import svgo from "imagemin-svgo";
import webp from "imagemin-webp";
 
keepfolder(["src/img/**/*.{jpg,png,gif,svg,webp}"], {
  plugins: [
    gifsicle(),
    svgo(),
    webp({
      quality: 50,
    }),
  ],
  replaceOutputDir: (output) => {
    return output.replace(/img\//, "../dist/img/");
  },
});
package.json
//追加
"type": "module",

動作確認

/src/img/配下に画像を格納します。(jpg、png、gif、svg、webp)

terminal
npm run watch:img

/src/img/配下の画像が圧縮されて/dist/img/配下にコピーされれば成功です。

distディレクトリの削除

以前の作業で生成したファイルがdistに残っているとトラブルにつながる恐れがあるため、削除します。

インストール

terminal
npm i rimraf -D

npmコマンド追加

package.json
"scripts": {
 "delete:dist": "rimraf dist"
}

動作確認

terminal
npm run delete:dist

distディレクトリが削除されれば成功です。

ファイルのコピー

今回は、sitemap.xml、robots.txt、humans.txt、manifest.json、favicon.ico、apple-touch-icon.pngをコピーするようにします。
あまり変更が入らないファイルのコピーを想定しているので、-w オプションは付けません。

インストール

terminal
npm i -D cpx

npmコマンド追加

package.json
"scripts": {
  "copy:sitemapxml": "cpx \"src/sitemap.xml\" dist/",
  "copy:robotstxt": "cpx \"src/robots.txt\" dist/",
  "copy:humanstxt": "cpx \"src/humans.txt\" dist/",
  "copy:manifestjson": "cpx \"src/manifest.json\" dist/",
  "copy:faviconico": "cpx \"src/favicon.ico\" dist/",
  "copy:apple-touch-iconpng": "cpx \"src/apple-touch-icon.png\" dist/"
}

動作確認

terminal
 npm run copy:sitemapxml

/src/sitemap.xmlが/dist/sitemap.xmlにコピーされれば成功です。

タスクの連携

これまで作ってきたタスクを連携して、コマンド1つで実行できるようにします。

npmコマンドの追加

package.json
"scripts": {
  "prewatch:all": "run-s delete:dist copy:sitemapxml copy:robotstxt copy:humanstxt copy:manifestjson copy:faviconico copy:apple-touch-iconpng",
  "watch:all": "run-p watch:pug watch:scss2cssprefix watch:ts watch:img start:server"
}

動作確認

terminal
npm run watch:all

HTML、CSS、JavaScriptのコンパイルを並列処理しているので、表示が崩れている場合は完了タイミングが異なっているのが原因と思われますので、リロードしてみてください。

コード整形

prettier

インストール

terminal
npm i -D prettier 
.prettierrc.json
{
  "semi": true,
  "trailingComma": "all",
  "printWidth": 120,
  "tabWidth": 2,
  "useTabs": false,
  "proseWrap": "preserve",
  "endOfLine": "auto"
}

設定は下記URLを参考に適宜変更してください。

.prettierrc

stylelint

インストール

terminal
npm i -D stylelint
npm i -D stylelint-config-recommended-scss
npm i -D stylelint-config-prettier

npm i -D stylelint-scss
npm i -D stylelint-order
npm i -D stylelint-prettier

npmコマンド追加

package.json
"scripts": {
  "lint:scss": "stylelint \"**/*.scss\"",
  "format:scss": "stylelint --fix \"**/*.scss\""
}

設定ファイル

.stylelintrc.json
{
  "extends": [
    "stylelint-config-recommended-scss",
    "stylelint-config-prettier"
  ],
  "plugins": [
    "stylelint-order",
    "stylelint-prettier"
  ],
  "rules": {
    "prettier/prettier": true,
    "indentation": 2,
    "declaration-colon-newline-after": null,
    "value-list-comma-newline-after": "never-multi-line",
    "order/properties-alphabetical-order": true
  }
}

設定は下記URLを参考に適宜変更してください。
.stylelintrc

動作確認

terminal
//SCSSファイルのリント
npm run lint:scss

//SCSSファイルの整形
npm run format:scss

Eslint

インストール

terminal
npm i -D eslint
npm i -D @typescript-eslint/parser
npm i -D eslint-config-prettier

npmコマンド追加

package.json
"scripts": {
  "lint:ts": "eslint src/ts/**/*.ts",
  "format:ts": "eslint src/ts/**/*.ts --fix"
}

設定ファイル

envの設定値 内容
"browser": true 無いとdocumentやconsoleなどでエラーが出てしまう
"node":true 無いとwebpack.config.jsonのdirname、module、requireでエラーが出てしまう
.eslintrc.json
{
  "parser": "@typescript-eslint/parser",
  "extends": [
    "eslint:recommended",
    "prettier"
  ],
  "parserOptions":  {
    "ecmaVersion": "latest",
    "sourceType":  "module"
  },
  "env": {
    "browser": true,
    "node": true
  },
  "root": true,
  "rules": {
    "quotes": ["error", "double"], //クォーテーションがシングルのときエラー
    "indent": ["error", 2]
  }
}

設定は下記URLを参考に適宜変更してください。
Configuring ESLint

動作確認

terminal
//TypeScriptファイルのリント
npm run lint:ts

//TypeScriptファイルの整形
npm run format:ts

SCSS、TypeScript一括整形

package.json
"scripts": {
"format:all":"run-p format:scss format:ts"
}

動作確認

terminal
//TypeScriptファイル、SCSSファイルの整形
npm run format:all

commit前にコード整形

インストール

terminal
npm i -D simple-git-hooks
npm i -D lint-staged
コマンド 内容
pre-commit コミット前に実行
pre-push プッシュ前に実行
package.json
"simple-git-hooks": {
  "pre-commit": "npx lint-staged"
},
 
"lint-staged": {
 "src/ts/*.ts": [
   "prettier --write",
   "eslint --fix --quiet"
 ],
 "src/scss/*.scss": [
   "prettier --write",
   "stylelint --fix --quiet"
 ]
}

pre-commit、pre-pushの有効化

terminal
npx simple-git-hooks
git/hooks/pre-commit、.git/hooks/pre-pushというファイルが作られます。
git commitを行うと、lint-stagedに指定したコマンドが実行されます。

テスト

Jestを使えるようにします。

インストール

terminal
npm i -D jest
npm i -D ts-jest
npm i -D @types/jest

npmコマンド追加

package.json
"scripts": {
  "test": "jest"
}

設定ファイル

jest.config.js
export default {
  roots: ["<rootDir>/src/ts/"],
  testMatch: ["**/__tests__/**/*.+(ts|tsx|js)", "**/?(*.)+(spec|test).+(ts|tsx|js)"],
  transform: {
    "^.+\\.(ts|tsx)$": "ts-jest",
  },
};

eslintrc.jsonの変更

Eslintでテストコードにエラーが出ないように、jestを追加

.eslintrc.json
"env": {
  "browser": true,
  "node":true,
  "jest": true
},

コードのサンプル

テスト用サンプルコード
src\ts\test_for_jest.ts
export const calc = (x: number, y: number) => {
  return x + y;
}
テストコード
src\ts__tests__\test_for_jest.spec.ts
import { calc } from "../test_for_jest";

describe("関数calcの動作確認", () => {
 it("3+4=7になる", () => {
   expect(calc(1, 8)).toBe(9);
 });
});

.spec.tsを変換しないようにtsconfigの設定変更

tsconfig.json
  "exclude": ["node_modules"]
  ↓
  "exclude": ["node_modules", "**/*.spec.ts"]

動作確認

terminal
npm run test

本番公開対応

/dist/配下のCSS、JavaScriptのminifyを行います。

インストール

terinal
npm i -D uglify-es
npm i -D clean-css-cli

npmコマンド追加

package.json
"scripts": {
  "min:css":"cleancss -o dist/css/style.css dist/css/style.css",
  "min:js": "uglifyjs dist/js/main.js -o dist/js/main.js",
  "prepare:all":"run-p min:js min:css"
}

動作確認

terminal
npm run prepare:all

/dist/配下のファイルをアップロードします

まとめ

使用時準備

termina;
git clone https://github.com/takeshisakuma/testament.git
cd testament
npm ci
npx simple-git-hooks

制作時

terminal
npm run watch:all

コード整形時

terminal
npm run format:all

テスト

terminal
npm run test

minify

terminal
npm run prepare:all

dist配下のファイルをそのままアップロードします

リポジトリ

10
6
0

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
10
6