Casual Developers Note

エンジニアやデザイナー向けの技術情報・英語学習情報・海外留学情報・海外旅行情報を提供中。世界を旅して人生を楽しもう。

  • ホーム
  • 技術 Tips & Tutorials
  • 技術塾
  • ライフハック
  • 海外留学
  • 英語学習
  • コラム
  • お問い合わせ
現在の場所:ホーム / アーカイブwebpack

2019年10月30日 By KD コメントを書く

ReactのためのEslintおよびPrettierの設定方法 ~Airbnb JavaScript Style Guideの適用~

ReactのためのEslintおよびPrettierの設定方法 ~Airbnb JavaScript Style Guideの適用~

Reactの開発環境でEslintおよびPretteirを設定する方法を紹介します。

はじめに

JavaScriptのコードフォーマッターと言えば「Eslint」と「Pretteir」を組み合わせるのが主流です。今回は、以前の記事「Create React Appを使わないでゼロからReactの開発環境を構築する方法(Webpack/Docker編)」をインプットにして、React用にゼロからEslintおよびPretteirを設定する方法を紹介します。

それでは、ReactにEslintおよびPrettierを設定していきましょう。

JavaScriptのコーディングスタイル

JavaScriptのコーディングスタイルは以下の3つが代表的です。

  • Airbnb JavaScript Style Guide
  • Google JavaScript Style Guide
  • JavaScript Standard Style

どれを使うのがベストか?ということになりますが、コーディングスタイルは主観に大きく左右されるので、綺麗な解を出すのは難しいです。なので、強い個人的な主張がなければ、それぞれのコーディングスタイルの特徴を理解した上で、どれが人気か?ということを見て判断するのが良いでしょう。尖ったスタイルは後でEslintとPretteirでカスタマイズできますからね。そこで、これらのコーディングスタイルを比較しているサイトとして「Comparing eslint-config-airbnb vs. eslint-config-google vs. standard」を見てみましょう。このサイトの結果では、Airbnbのコーディングスタイルが一番人気があり良さそうです。

ということで、今回はコーディングスタイルとして「Airbnb JavaScript Style Guide」を適用します。

ReactにEslintおよびPrettierを設定する

前提

以下の設定が事前に完了している必要があります。

  • NodeJSがインストールされていること
  • 「Create React Appを使わないでゼロからReactの開発環境を構築する方法(Webpack/Docker編)」の設定が完了していること

EslintおよびPretteirのモジュールをインストールする

ReactのプロジェクトにEslint、Pretteir、関連モジュールをインストールします。

$ cd my-react-app
$ yarn add --dev eslint eslint-config-airbnb eslint-plugin-import eslint-plugin-jest eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-react-hooks
$ yarn add --dev eslint-plugin-babel eslint-plugin-flowtype
$ yarn add --dev babel-eslint eslint-loader
$ yarn add --dev prettier eslint-config-prettier eslint-plugin-prettier
$ yarn add --dev husky lint-staged

Pretteirの設定をする

Pretteirの設定ファイルを作成し、設定を書きます。

$ touch prettier.config.js

prettier.config.js

module.exports = {
  trailingComma: 'es5',
  tabWidth: 2,
  semi: false,
  singleQuote: true,
}

流行りのセミコロン無しの設定にしています。

また、設定ファイルのフォーマットは、Pretteirに限らず、JSON、YAML、JavaScriptが選択可能になっていることが多いですが、結局JavaScriptで設定ファイルを書くのが一番使いやすいと感じています。コメントが書けたり、設定を整理したい時に便利だからです。

Eslintの設定をする

Eslintの設定ファイルを作成して、設定を書きます。

$ yarn eslint --init
...
? How would you like to use ESLint? To check syntax, find problems, and enforce code style
? What type of modules does your project use? JavaScript modules (import/export)
? Which framework does your project use? React
? Does your project use TypeScript? No
? Where does your code run? Browser
? How would you like to define a style for your project? Use a popular style guide
? Which style guide do you want to follow? Airbnb (https://github.com/airbnb/javascript)
? What format do you want your config file to be in? JavaScript
Checking peerDependencies of eslint-config-airbnb@latest
The config that you've selected requires the following dependencies:
...
? Would you like to install them now with npm? No
...

.eslintrc.js

module.exports = {
  env: {
    browser: true,
    es6: true,
    jest: true,
  },
  extends: [
    'airbnb',
    'airbnb/hooks',
    'plugin:flowtype/recommended',
    'plugin:jest/recommended',
    'plugin:jest/style',
    'prettier',
    'prettier/babel',
    'prettier/react',
    'prettier/flowtype',
  ],
  globals: {
    Atomics: 'readonly',
    SharedArrayBuffer: 'readonly',
  },
  parser: 'babel-eslint',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 2018,
    sourceType: 'module',
  },
  plugins: ['babel', 'flowtype', 'jest', 'prettier'],
  rules: {
    'prettier/prettier': 'error',
    'react/jsx-filename-extension': 'off',
    'react/prop-types': 'off',
    'react/default-props-match-prop-types': 'off',
    'react/require-default-props': 'off',
    'flowtype/no-types-missing-file-annotation': 'off',
    'flowtype/define-flow-type': 'warn',
    'flowtype/use-flow-type': 'warn',
  },
}

自動作成された設定に、Babel、Flow、Jest、Pretteirのための設定を追加してあります。

Webpackに設定を追加する

Webpackで開発中にEslintを毎回実行するようにローダーの設定を追加します。

$ vi webpack.config.babel.js
{
...
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'eslint-loader',
        options: {
          fix: true,
        },
      },
...
    ],
  },
...
}

コミット時にリンターを実行する設定をする

コミット時に必ずチェックするようにしておけば安心です。

$ vi package.json
{
...
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "src/**/*.{js,jsx}": [
      "yarn eslint --fix",
      "git add"
    ]
  },
...
}

以上で完了です。あとは、エラーがになる箇所があればルールに従って修正していってください。

最後に

いかがでしたか?これでゼロからReact用にEslintおよびPretteirを設定できるようになったことでしょう。それでは。

環境

  • NodeJS: v12.12.0
  • eslint: 6.6.0
  • eslint-config-airbnb: 18.0.1
  • eslint-plugin-import: 2.18.2
  • eslint-plugin-jest: 23.0.2
  • eslint-plugin-jsx-a11y: 6.2.3
  • eslint-plugin-react: 7.16.0
  • eslint-plugin-react-hooks: 2.2.0
  • eslint-plugin-babel: 5.3.0
  • eslint-plugin-flowtype: 4.3.0
  • babel-eslint: 10.0.3
  • eslint-loader: 3.0.2
  • prettier: 1.18.2
  • eslint-plugin-prettier: 3.1.1
  • eslint-config-prettier: 6.5.0
  • husky: 3.0.9
  • lint-staged: 9.4.2

カテゴリ : 技術 Tips & Tutorials タグ : eslint, prettier, react, webpack

2019年9月30日 By KD コメントを書く

Create React Appを使わないでゼロからReactの開発環境を構築する方法(Webpack/Docker編)

Create React Appを使わないでゼロからReactの開発環境を構築する方法(Webpack/Docker編)

create-react-appを使わないでReactの開発環境を構築する方法を紹介します。

はじめに

近年のJavaScriptフレームワークはCLIを使ってワン・コマンドで設定できるようになっています。Reactではそのためのコマンドとしてcreate-react-appが提供されています。creat-react-appは簡単にReactを設定できる反面、設定が隠蔽されてしまい、細かい設定をするためにはejectする羽目になります。しかし、ejectをしてしまえば最後、create-react-appがアップデートされてもアップデートできなくなってしまいます。では、プロダクションなどで設定を細かく設定して管理したい場合はどうすればよいでしょうか?そういう人は自分でゼロから設定しましょう。

ということで、今回はcreate-react-appを使わないで、Reactの開発環境を構築していきましょう。

Reactの開発環境の構築方法

それでは、Reactの設定をしましょう。

前提

以下の設定が完了している必要があります。

  • NodeJSがインストールされていること
  • Yarnがインストールされていること
  • Dockerがインストールしていること

詳しくは、「環境」を参照して下さい。

ベースの作成とパッケージのインストール

必要なフォルダおよびファイルを作成し、必要なパッケージをインストールします。

$ mkdir my-react-app
$ cd my-react-app/
$ yarn init -y
$ mkdir public src
$ touch public/index.html
$ touch src/index.js src/index.css
$ touch src/App.js src/App.test.js src/App.css
$ touch .babelrc webpack.config.babel.js
$ touch jest.config.js
$ mkdir __mocks__
$ touch __mocks__/styleMock.js
$ touch __mocks__/fileMock.js
$ yarn add --dev flow-bin flow-typed
$ yarn flow init
$ tree -aI node_modules
.
├── .babelrc
├── .flowconfig
├── __mocks__
│   ├── fileMock.js
│   └── styleMock.js
├── build
├── jest.config.js
├── package.json
├── public
│   └── index.html
├── src
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── index.css
│   └── index.js
├── webpack.config.babel.js
└── yarn.lock
$ yarn add react react-dom
$ yarn add --dev jest jest-enzyme enzyme enzyme-adapter-react-16
$ yarn add --dev @babel/core @babel/preset-env @babel/preset-react @babel/preset-flow @babel/register babel-jest
$ yarn add --dev webpack webpack-cli webpack-dev-server
$ yarn add --dev html-webpack-plugin mini-css-extract-plugin uglifyjs-webpack-plugin optimize-css-assets-webpack-plugin clean-webpack-plugin
$ yarn add --dev babel-loader css-loader html-loader
$ vi package.json
...
  "scripts": {
    "start": "webpack-dev-server --open --mode development",
    "build": "webpack --mode production",
    "test": "jest"
  }
...

準備ができました。

設定を書く

それでは、ファイルの中身を書いていきましょう。

.babelrc

{
  "presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-flow"]
}

jest.config.js

module.exports = {
  moduleNameMapper: {
    '\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
      '/__mocks__/fileMock.js',
    '\.(css|less)$': '/__mocks__/styleMock.js',
  },
};

__mocks__/styleMock.js

module.exports = {};

__mocks__/fileMock.js

module.exports = 'test-file-stub';

.flowconfig

[ignore]
.*/node_modules/.*
.*/flow-typed/.*
.*/build/.*
.*\.(test|spec)\.js
.*/build/.*
.*webpack.*
.*jest\.config\.js
<PROJECT_ROOT>/src/index\.js

[include]

[libs]

[lints]

[options]
all=true

[strict]

webpack.config.babel.js

import path from 'path';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import UglifyJsPlugin from 'uglifyjs-webpack-plugin';
import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin';
import { CleanWebpackPlugin } from 'clean-webpack-plugin';

const outputPath = path.resolve(__dirname, 'build');

export default {
  entry: './src/index.js',
  output: {
    filename: '[name].[hash].js',
    path: outputPath,
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
      {
        test: /\.html$/,
        loader: 'html-loader',
      },
    ],
  },
  devServer: {
    contentBase: outputPath,
    compress: true,
    port: 3000,
  },
  devtool: 'eval-source-map',
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html',
    }),
    new MiniCssExtractPlugin({
      filename: '[name].[hash].css',
    }),
    new CleanWebpackPlugin(),
  ],
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        uglifyOptions: {
          compress: {
            drop_console: true,
          },
        },
      }),
      new OptimizeCSSAssetsPlugin(),
    ],
  },
};

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>My React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(, document.getElementById('root'));

index.css

* {
  margin: 0;
}

App.js

import React, { useState } from 'react';
import './App.css';

type Props = {
  initialCount: number,
};

function App({ initialCount }: Props) {
  const [count, setCount] = useState(initialCount);

  return (
    <div className="App" data-test="component-app">
      <header className="App-header">
        <p>My React App without Create React App!</p>
        <p>Count: {count}</p>
        <div>
          <button onClick={() => setCount(count + 1)}>+1</button>
          <button onClick={() => setCount(count - 1)}>-1</button>
          <button onClick={() => setCount(initialCount)}>clear</button>
        </div>
      </header>
    </div>
  );
}

App.defaultProps = {
  initialCount: 0,
};

export default App;

App.css

.App {
  text-align: center;
}

.App-header {
  background-color: #09d3ac;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 4vmin);
  color: white;
}

button {
  margin: 0 5px;
  padding: 10px;
  width: 200px;
  font-size: calc(10px + 4vmin);
  border-radius: 10px;
}

App.test.js

import React from 'react';
import Enzyme, { shallow } from 'enzyme';
import EnzymeAdapter from 'enzyme-adapter-react-16';
import App from './App';

Enzyme.configure({ adapter: new EnzymeAdapter() });

it('renders without crashing', () => {
  const wrapper = shallow(<App />);
  const appComponent = wrapper.find(`[data-test="component-app"]`);

  expect(wrapper).toBeTruthy();
  expect(appComponent.length).toBe(1);
});

完成です。

今回のWebpackの設定は開発用とプロダクション用で分けていませんが、実際には分けて作り、webpack-mergeなどを使って共通化すると良いでしょう。

今回のJestの設定は公式ドキュメントの通りにしてあります。

なお、EslintやPrettierもプロジェクトのスタイリングルールに応じて設定した方が良いでしょう。

動作確認

まずは開発環境を起動してみましょう。

$ yarn start
...
ℹ 「wds」: Project is running at http://localhost:3000/
...
ℹ 「wdm」: Compiled successfully.

ブラウザで「localhost:3000」が表示されます。

NewImage

カウンターの動作確認もしてみましょう。

NewImage

NewImage

NewImage

OKですね。

次に、テスト実行してみましょう。

$ yarn test
...
 PASS  src/App.test.js
  ✓ renders without crashing (10ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        5.667s
Ran all test suites.
✨  Done in 7.68s.

テストもパスしました。

最後に、ビルドしてみましょう。

$ yarn build
$ ls build/
index.html                     main.babca1870d3e34b4c183.css  main.babca1870d3e34b4c183.js

ビルドも成功しました。

これで、Reactの設定は完了しました。

Docker化する方法

それでは、Docker上で起動するようにしていきましょう。

ファイルの作成

必要なファイルを作成します。

$ touch Dockerfile.dev docker-compose.yml

設定を書く

Dockerの設定を書きましょう。

Dockerfile.dev

FROM node:12.10-alpine

WORKDIR /app

RUN apk update \
  && apk --no-cache add git ca-certificates wget

RUN wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub \
  && wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.30-r0/glibc-2.30-r0.apk \
  && apk --no-cache add glibc-2.30-r0.apk

COPY package.json .
COPY yarn.lock .
RUN yarn install

COPY .flowconfig .
RUN yarn global add flow-typed \
  && flow-typed install

COPY . .

EXPOSE 3000

CMD yarn start

docker-compose.yml

version: "3"

services:
  web:
    command: "yarn start --host 0.0.0.0 --port 3000"
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - /app/node_modules
      - .:/app

完成です。

FlowはAlpine上で実行する際に問題があり、こちらにissueが発行されています。結局、glibcを入れるか、flowのバイナリーを入れるかで対処する必要があり、今回は前者にしました。

動作確認

Dockerで起動できるか確認してみましょう。

$ docker-compose build --no-cache
$ docker-compose up -d
$ docker-compose ps
       Name                     Command               State           Ports         
------------------------------------------------------------------------------------
my-react-app_web_1   docker-entrypoint.sh yarn  ...   Up      0.0.0.0:3000->3000/tcp

ブラウザで「localhost:3000」を開けば、正しく表示されます。

これでDocker化まで完了しました。

おまけ

さらに、Webpackに開発用の設定を追加していきましょう。

画像を読み込むための設定

画像などのアセットを読み込むための設定を追加します。画像をWebpackで利用するには、url-loaderおよびfile-loaderのローダーを追加します。

$ yarn add --dev file-loader url-loader
$ vi webpack.config.babel.js
{
...
  module: {
    rules: [
...
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10 * 1024,
              name: '[name].[hash:8].[ext]',
              outputPath: 'assets',
            },
          },
        ],
      },
...
    ],
  },
...
}

「url-loader」でファイルをbase64に変換してCSSに埋め込みます。ファイルのサイズがリミットを超える場合は「file-loader」でファイルをそのまま読み込みます。base64はファイルを都度読み込む必要がないのでページの読み込みを早くできますが、常にファイルをそのまま扱いたい場合は「file-loader」だけで良いです。

Polyfillの設定方法

古いブラウザに対応するために、BabelにPolyfillを追加しましょう。

$ yarn add core-js@3

.babelrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ],
    "@babel/preset-react",
    "@babel/preset-flow"
  ]
}

@babel/polyfillはBabelの7.4.0から非推奨になっています。上記の設定で、必要なPolyfillだけをcorejsからインポートして使われるようになります。詳しくは、公式ドキュメントを参照して下さい。

HMR(Hot Module Replacement)の設定方法

webpack-dev-serverでは、デフォルトでdevServer.inlineが有効になっており、ライブリロードが実行されます。ライブリロードはソースコードを修正するたびにブラウザをリロードする機能ですが、一つのコンポーネントを修正するたびにブラウザをリロードするのは効率がよくありません。そこで、HMR(Hot Module Replacement)を有効することで、リロードすることなく、修正したコンポーネントだけ更新するようにしましょう。

webpack.config.babel.js (抜粋)

...
import webpack from 'webpack';
...

export default {
...
  devServer: {
    ...
    hot: true,
    ...
  },
...
  plugins: [
    ...
    new webpack.HotModuleReplacementPlugin(),
  ],
...
};

devServer.hotを有効にし、かつ、HotModuleReplacementPluginを設定しました。

起動してみると、以下のようにHMRが有効になっていることが分かります。

NewImage

react-hot-loaderの設定方法

Stateを保持したままコンポーネントの修正を反映するために、react-hot-loaderおよび@hot-loader/react-domを設定しましょう。

$ yarn add react-hot-loader @hot-loader/react-dom

.babelrc (抜粋)

{
  "plugins": ["react-hot-loader/babel"],
...
}

webpack.config.babel.js (抜粋)

...

export default {
...
  resolve: {
    alias: {
      'react-dom': '@hot-loader/react-dom',
    },
  },
};

App.js (抜粋)

...
import { hot } from 'react-hot-loader/root';
...
export default hot(App);

最後に

いかがでしたか?これでcreate-react-appに頼ることなく、自分でReactを設定できるようになったことでしょう。それでは。

環境

  • NodeJS: v12.11.0
  • Yarn: 1.17.3
  • Docker: 19.03.2
  • react: 16.10.0
  • react-dom: 16.10.0
  • react-hot-loader: 4.12.14
  • @hot-loader/react-dom: 16.9.0
  • core-js: 3
  • @babel/core: 7.6.2
  • @babel/preset-env: 7.6.2
  • @babel/preset-flow: 7.0.0
  • @babel/preset-react: 7.0.0
  • @babel/register: 7.6.2
  • babel-jest: 24.9.0
  • jest: 24.9.0
  • jest-enzyme: 7.1.1
  • enzyme: 3.10.0
  • enzyme-adapter-react-16: 1.14.0
  • flow-bin: 0.108.0
  • flow-typed: 2.6.1
  • webpack: 4.41.0
  • webpack-cli: 3.3.9
  • webpack-dev-server: 3.8.1
  • clean-webpack-plugin: 3.0.0
  • html-webpack-plugin: 3.2.0
  • optimize-css-assets-webpack-plugin: 5.0.3
  • uglifyjs-webpack-plugin: 2.2.0
  • mini-css-extract-plugin: 0.8.0
  • babel-loader: 8.0.6
  • css-loader: 3.2.0
  • html-loader: 0.5.5
  • url-loader: 2.2.0
  • file-loader: 4.2.0

カテゴリ : 技術 Tips & Tutorials タグ : babel, create-react-app, docker, flow, hot-module-replacement, polyfill, react, webpack

2018年10月22日 By KD コメントを書く

Webpack時代の終焉か?設定ファイルゼロのビルドツールParcelクイック入門

Webpack時代の終焉か?設定ファイルゼロのビルドツールParcelクイック入門

Webアプリケーションのビルドツールと言えば、2018年度はWebpackの独壇場でした。しかし、時代が進むにつれてあらゆるツールは進化しています。今回は設定ファイルゼロの次世代ビルドツールParcelを紹介します。

はじめに

Webpackはとても素晴らしいビルドツールです。JavaScriptのビルドに留まらず、CSSや画像などを全てJavaScriptの世界に取り込んだ発想はとても新しいものでした。今Webアプリケーションの開発を始める場合、特にフロントエンドの開発ではWebpackを使わないという選択肢は無いでしょう。そして、流行りのプラグイン方式をとっていることも大きいです。多くのデベロッパーがWebpackのプラグインを開発してWebpackのコミュニティーに間接的に貢献しています。私もプラグインを開発した一人です。

しかし、Webpackには大きな問題があります。それは、プロダクションレベルの設定ファイルを書くと、設定ファイルが複雑化してしまう点です。Webpackに限った話ではありませんが、設定ファイル地獄は誰もが経験し、うんざりしているのは事実です。

そこに目をつけてだと思いますが、「設定ファイルゼロ」を掲げて開発された次世代ビルドツールが「Parcel」です。もし設定ファイルがゼロでWebpackでできることを全て実現できるのであれば、Webpackを使う理由はありません。設定ファイルが無いほうが良いに決まっているからです。それを実現できるかどうかがParcelへの期待であり、おそらく2019年には答えが出ることでしょう。

今回は、そんな注目のParcelをささっと入門してみましょう。

Webサイトのビルド

まずは、一番ベーシックなHTMLとCSSで構成されたWebサイトをビルドしてみましょう。

ベースを作る

ベースとなるフォルダとファイルを作り、Parcelをインストールします。

$ mkdir website
$ cd website/
$ yarn init -y
$ yarn add --dev parcel-bundler
$ mkdir -p src/js
$ mkdir -p src/css
$ touch src/index.html
$ touch src/js/index.js
$ touch src/js/lib.js
$ touch src/css/index.css
$ touch .postcssrc

実装する

非常に簡単なサイトを作ってみましょう。

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Parcel Tutorials</title>
</head>

<body>
  <h1>Parcel Tutorials</h1>
  <p>This is a tutorial for Parcel beginners.</p>

  <script src="./js/index.js"></script>
</body>

</html>

index.css

h1 {
  color: orange;
}

p {
  font-style: oblique;
}

lib.js

const currentYear = new Date().getFullYear();

export {
  currentYear
};

index.js

普通にCSSをHTMLから読み込んでも良いのですが、あまりにつまらないのでCSS Modulesを使ってJavaScriptから読み込むことにしましょう。

import { currentYear } from './lib';
import '../css/index.css';

console.log(`Hello Parcel! It's a new generation build tool in ${currentYear}.`);

.postcssrc

CSS Modulesを使用するので、PostCSSの設定ファイルを準備しましょう。

{
  "modules": true
}

この状態でParcelを起動するだけでpostcss-modulesのパッケージが自動的にインストールされます。

package.json

開発用とプロダクションビルド用のコマンドを追加します。

{
...
  "scripts": {
    "start": "parcel src/index.html --port 8080",
    "build": "parcel build src/index.html --out-dir build"
  }
}

デフォルトのままでもよいのですが、せっかくなのでオプションで2箇所に変更を加えています。1つ目は、ParcelでWebサイトを動かす場合はデフォルトのポートは1234ですが、オプションで8080に変更しています。2つ目は、ParcelでWebサイトをビルドした場合のデフォルトのディレクトリはdistですが、オプションでbuildに変更しています。

動作確認

それでは実際に動かしてみましょう。

まずは開発用にHMR(Hot Module Replacement)が有効な状態でWebサイトを表示します。

$ yarn start
...
Server running at http://localhost:8080
✨  Built in 1.64s.

ブラウザから「http://localhost:8080」にアクセスすると。

NewImage

正しく表示されています。

この状態で、HTML、CSS、JavaScriptを変更すると、自動的にリロードされます。

次に、このWebサイトをプロダクション用にビルドしてみます。

$ yarn build
...
✨  Built in 516ms.

build/js.78f7eff6.js     1.5 KB    50ms
build/js.78f7eff6.map     654 B     4ms
build/index.html          410 B    10ms
build/js.af1e5064.css      37 B    10ms
✨  Done in 1.31s.
$ tree build/
build/
├── index.html
├── js.78f7eff6.js
├── js.78f7eff6.map
└── js.af1e5064.css

しっかりとビルドできていますね。

SASSのビルド

次に、CSSで書いていた部分をSASSで書き直してみましょう。

ベースを修正する

CSSファイルとPostCSSの設定ファイルおよび依存モジュールを削除して、SCSSファイルを追加します。

$ rm src/css/index.css
$ rm .postcssrc
$ yarn remove postcss-modules
$ touch src/css/index.scss

ソースコードを修正する

index.scss

簡単なSCSSファイルを書きます。

$primary-color: blue;

h1 {
  color: $primary-color;
}

p {
  font-style: oblique;
}

index.js

CSSファイルを読み込んでいた箇所をSCSSで読み込むように修正¥します。

import { currentYear } from './lib';
import '../css/index.scss';

console.log(`Hello Parcel! It's a new generation build tool in ${currentYear}.`);

この状態でParcelを起動するだけでsassのパッケージが自動的にインストールされます。

動作確認

先ほどと同じくParcelを起動します。

$ yarn start
...
Server running at http://localhost:8080
✨  Built in 2ms.

ブラウザで「localhost:8080」を表示します。

NewImage

正しくSCSSが読み込まれています。

モダンJavaScriptの構文のビルド(Babelプラグイン)

BabelプラグインでモダンなJavaScriptの構文を追加してみましょう。

ベースを修正する

Babelを使うので、設定ファイルを追加します。

$ touch .babelrc

ソースコードを修正する

.babelrc

今回はBebelプラグイン「@babel/plugin-proposal-class-properties」を追加して使います。

{
  "plugins": [
    "@babel/plugin-proposal-class-properties"
  ]
}

index.jsを修正する

Babelプラグインで追加したクラスのプロパティを使った形にファイルを修正します。

import { currentYear } from './lib';
import '../css/index.scss';

class Greeting {
  message = "Hello Parcel and Babel! It's a new generation build tool in %s";

  display(date) {
    console.log(this.message, date);
  }
}

const greeting = new Greeting();
greeting.display(currentYear);

動作確認

Parcelを起動してみましょう。

$ yarn start
...
Server running at http://localhost:8080
✨  Built in 56ms.

ブラウザで「localhost:8080」を表示します。

NewImage

BabelでモダンなJavaScript構文が使用できました。

Reactアプリケーションのビルド

最後に、少しだけ実践的な話題として、簡単なReactアプリケーションをビルドしてみましょう。

Reactをセットアップする

まずは、必要なフォルダとファイルを作り、ParcelとReactのモジュールをインストールします。

$ mkdir parcel-react
$ cd parcel-react/
$ yarn init -y
$ yarn add --dev parcel-bundler
$ yarn add react react-dom
$ touch src/index.html
$ touch src/index.js
$ touch src/index.css
$ touch src/App.js
$ touch src/App.css

実装する

package.json

先程と同じく開発用とプロダクションビルド用のコマンドを追加します。

{
...
  "scripts": {
    "start": "parcel src/index.html --out-dir public",
    "build": "parcel build src/index.html --out-dir build"
  }
}

index.html

シングルページの起点となるHTMLファイルを作成します。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>Parcel and React</title>
</head>

<body>
  <div id="root"></div>
  <script src="./index.js"></script>
</body>

</html>

Reactの起点となるrootクラスと、Reactの起点となるindex.jsスクリプトの読み込みを書きます。

index.js

Reactの起点となるJavaScriptを書きます。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

index.css

ページ全体に適用するCSSを書きます。

body {
  margin: 0;
  padding: 0;
}

App.js

簡単なJSXを書きます。

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <h1>Parcel and React</h1>
        <p>It's a really easy way to build React!</p>
      </div>
    );
  }
}

export default App;

App.css

Reactっぽい色のスタイルを書きます。

.App {
  text-align: center;
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.App h1 {
  color: #61dafb;
}

.App p {
  color: white;
}

動作確認

それでは、Parcelを起動してReactプロジェクトが動くか見てみましょう。

$ yarn start
...
Server running at http://localhost:1234
✨  Built in 5.31s.

ブラウザで「localhost:1234」を表示します。

NewImage

そして、プロダクション用にビルドもしてみましょう。

$ yarn build
...
✨  Built in 6.42s.

build/src.577091b8.map    210.56 KB     59ms
build/src.577091b8.js     104.07 KB    5.07s
build/index.html              322 B    1.23s
build/src.c71201e7.css        206 B    4.35s
✨  Done in 8.76s.
$ ls build/
index.html        src.577091b8.js   src.577091b8.map  src.c71201e7.css

完璧ですね。ここまでで設定ファイルは完全にゼロです。

最後に

いかがでしたか?設定ファイルゼロのParcelの凄さが分かったでしょうか?Webpackに完全に入れ替わるかどうかはまだわかりませんが、JavaScript界隈は高速で古いツールを捨てていくので、可能性は高いでしょう。2019年のParcelの進化に期待ですね。それでは。

環境

  • yarn: 1.10.1
  • parcel-bundler: 1.10.3

カテゴリ : 技術 Tips & Tutorials タグ : build-tool, parcel, webpack

ブログ更新情報や海外の関連情報などを配信する無料メルマガ

Sponsored Links

About Author

KD

世界を旅し日本を愛するエンジニア。大学でコンピュータサイエンスの楽しさを学び、日本の大手IT企業で働く中で、新しい技術やスケールするビジネスが北米にある事に気づく。世界に挑戦するための最大の壁が英語であったため、フィリピン留学およびカナダ留学を経て英語を上達させた。現在は日本在住でエンジニアとして働きつつ、次の挑戦に備えて世界の動向を注視している。挑戦に終わりはない。このブログでは、エンジニアやデザイナー向けの技術情報から、海外に留学したい人向けの留学情報、海外に興味がある人向けの海外旅行情報など、有益な情報を提供しています。

https://casualdevelopers.com/

最近の投稿

  • 2020年JS周辺のバックエンド寄りの注目技術!ネクストNodeJSの「Deno」と分散型パッケージレジストリの「Entropic」の紹介

    2020年JS周辺のバックエンド寄りの注目技術!ネクストNodeJSの「Deno」と分散型パッケージレジストリの「Entropic」の紹介

    2020年1月13日
  • 今さら聞けないJavaによる関数型プログラミング入門 ~ラムダ式、ストリーム、関数型インターフェース~

    今さら聞けないJavaによる関数型プログラミング入門 ~ラムダ式、ストリーム、関数型インターフェース~

    2019年11月4日
  • ReactのためのEslintおよびPrettierの設定方法 ~Airbnb JavaScript Style Guideの適用~

    ReactのためのEslintおよびPrettierの設定方法 ~Airbnb JavaScript Style Guideの適用~

    2019年10月30日
  • BashからZshに移行する方法(Mac編)

    BashからZshに移行する方法(Mac編)

    2019年10月21日
  • Create React Appを使わないでゼロからReactの開発環境を構築する方法(Webpack/Docker編)

    Create React Appを使わないでゼロからReactの開発環境を構築する方法(Webpack/Docker編)

    2019年9月30日

カテゴリ

  • 技術 Tips & Tutorials (100)
  • 技術塾 (6)
  • ライフハック (26)
  • 海外留学 (12)
  • 英語学習 (3)
  • コラム (6)

アーカイブ

最高の学習のために

人気記事ランキング

  • MySQLで「ERROR 2003 (HY000): Can't connect to MySQL server」と怒られた時の対処法
    MySQLで「ERROR 2003 (HY000): Can't connect to MySQL server」と怒られた時の対処法
  • SAKURAのメールボックスで独自ドメインのメールを設定し、Gmail経由で送受信する方法
    SAKURAのメールボックスで独自ドメインのメールを設定し、Gmail経由で送受信する方法
  • Jupyter Notebookで「The kernel appears to have died. It will restart automatically.」というエラーが出た場合の原因と対処法
    Jupyter Notebookで「The kernel appears to have died. It will restart automatically.」というエラーが出た場合の原因と対処法
  • Expressで「Cannot set headers after they are sent to the client」と怒られた時の対処法
    Expressで「Cannot set headers after they are sent to the client」と怒られた時の対処法
  • Amazon EC2インスタンスにSSHできなくなった時の対処法
    Amazon EC2インスタンスにSSHできなくなった時の対処法
  • SLF4JとLogbackによるJavaのロギング入門(SLF4J + Logback + Lombok)
    SLF4JとLogbackによるJavaのロギング入門(SLF4J + Logback + Lombok)
  • SpringBootのProfile毎にプロパティを使い分ける3つの方法
    SpringBootのProfile毎にプロパティを使い分ける3つの方法
  • [tips][perl] Perlで文字コードをいい感じに処理する方法
    [tips][perl] Perlで文字コードをいい感じに処理する方法
  • 爆速でJenkinsをマスターしよう(GitHubアカウント統合編) ~ JenkinsのGitHub Organizationの設定方法 ~
    爆速でJenkinsをマスターしよう(GitHubアカウント統合編) ~ JenkinsのGitHub Organizationの設定方法 ~
  • Go言語のためのVisual Studio Codeの設定方法
    Go言語のためのVisual Studio Codeの設定方法

Bitcoin寄付 / BTC Donation

Bitcoinを寄付しよう

BTC
Select Payment Method
Personal Info

Donation Total: BTC 0.0010

このブログの運営のためにBitcoinでの寄付を募集しています。お気持ち程度の寄付を頂けると管理者の励みになります。

Bitcoin寄付について知りたい方はこちらの記事へ

ビットコイン取引ならここ

  • ホーム
  • 技術 Tips & Tutorials
  • 技術塾
  • ライフハック
  • 海外留学
  • 英語学習
  • コラム
  • サイトマップ
  • タグ一覧
  • プライバシーポリシー
  • お問い合わせ

Copyright © 2023 KD - Casual Developers Notes