Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Setup a project with Webpack4 and learn some React concepts along the way

NotificationsYou must be signed in to change notification settings

CodeSigils/webpack4-react16-setup

Repository files navigation

A demo of basic (and some advanced) React concepts in a React app.Also a webpack4 setup guide useful for development, with tips and somenecessary yet light reading along the way.

★ Note: No script automated React build will be used here. More and more notes and tips will be added in the future. Keep reading, or scroll to Webpack setup section.

Table of Contents:

1. Setting-up the environment.

1.1 - Install Yarn

# Add repo  curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg| sudo apt-key add -echo"deb https://dl.yarnpkg.com/debian/ stable main"| sudo tee /etc/apt/sources.list.d/yarn.list# Install with yarn included Node (see next line)  sudo apt-get update&& sudo apt-get install yarn# When NVM present avoid node installation with  sudo apt-get install --no-install-recommends yarn

1.2 - Install NVM

# Get NVM the scary way  wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh| bash

1.3 - NVM and Yarn path setup in your .zshrc:

# NVM Node Version Managerexport NVM_DIR="$HOME/.nvm"  [-s"$NVM_DIR/nvm.sh" ]&&\."$NVM_DIR/nvm.sh"# This loads nvm  [-s"$NVM_DIR/bash_completion" ]&&\."$NVM_DIR/bash_completion"# This loads nvm bash_completion# Yarn (must be placed after nvm)# export PATH=$HOME~/.yarn/bin:$PATHexport PATH="$PATH:`yarn global bin`"

1.4 - Use of yarn: Initialize a project withyarn init.

Runyarn help and read about global options for setup.

★ Tip: Yarn is ideal withNVM since is not forcing you to migrate your globally installed modules every time you changeNode version.

1.5 - Adding scripts section inpackage.json

People are using the "scripts" section of package.json file in all sorts of ways. There is also one famous article about how to replace build automation tools using only piped commands in scripts.

{// ..."description":"React ecosystem demo",// Note: Comments will not work on JSON files// Define scripts here and run them with "npm run ..." or "yarn""scripts":{"serve":"webpack-dev-server --watch --config ./config/webpack.dev.js --mode development","dev":"webpack --mode development","build":"webpack --mode production","watch":"webpack --config ./config/webpack.dev.js --watch --mode development","lint":"./node_modules/.bin/eslint -v --color ./src/**/*.js","pretty":"./node_modules/.bin/prettier ./src/**/*.js --write","precommit":"pretty-quick --staged"},// ... Comments will not work on JSON files}

1.8 - Handling Early versions of Node and older browsers


2 - Babel and Babel presets (Official and experimental) installation and setup

  • Read about theBabel transpiler:JavaScript Transpilers: What They Are & Why We Need Them

  • Thebabel-cli: Babel comes with a built-in CLI which can be used to compile files from the command line. Install it with:yarn add babel-cli --dev

  • Read aboutBabel presets.

    • ★ Tip:babel-preset-es2015 is deprecated. Usebabel-preset-env withbabel-preset-stage-0 instead. Thestage-0 allows experimental features.
    • Thebabel-preset-env: is all about latest stable JS features. It allows us to use 'const', 'import from', arrow functions andmany more ...
      • Installation:yarn add babel-preset-env --dev
      • ★ Tip: run it from terminal withnode ./node_modules/.bin/babel index.js -o ./bundle.js --presets=env
  • We are going to define Babel presets in webpack so we don't need the.babelrc file.

2.1 - ES6 features quick review

  • ES6 modules:import path from 'path'
  • Arrow functions:a => a * 2
  • Classes:class MyClass extends Framework.Class { }
  • Object literals:{ foo }
  • Template Strings:Foo ${bar}
  • Destructing:({ a }) => { console.log(a) }
  • Let/Const:const foo = 'Hello' let bar='World'

3. Code-Linting, Code-Formating and Git hooks

Take a look at ESLint, "the pluggable linting utility for JavaScript and JSX"ineslint.org.

Take a look at Prettier, "the opinionated code formatter" inprettier.io.

Take a look atHusky

3.1 -Eslint andPrettier plugins for VSCode

Install Prettier and ESlint plugins from VSCode marketplace:

3.2 - Bring all together

  • We can runeslint --init interactive cli in our project path and answer the questions about how we want to style our code. First install Eslint with prettier plugin rules:

    yarn add -D eslint prettier eslint-config-prettier eslint-plugin-prettier

    If we want to follow'airbnb' style-guide and combine a custom configuration with prettier, we can run in the terminal:

      $ ./node_modules/.bin/eslint --init? How would you like to configure ESLint? Use a popular style guide? Which style guidedo you want to follow? Airbnb? Do you use React? Yes? What formatdo you want your config file to be in? JSON
  • Use prettier for staged files to git and only watch on changed files. To do this we needhusky. Thelink-staged library will output only changed files in the console before the commit !. For this we need to add some configuration lines in ourpackage.json file to define the order of execution, but theprettier-quick lib relieves us from this. However if you don't want to use this little automation, add this intopackage.json after the scripts section:

    {//..."lint-staged":{"*.js":["yarn-lint","prettier --write","git add"]}},// ...

yarn add -D husky lint-staged prettier-quick

  • Test it with./node_modules/.bin/prettier ./src/*.js --write, configure it with.eslintrc and automated inpackage.json file:
{/* 1. ---- ./.eslintrc.json file ---- */"parser":"babel-eslint","extends":["prettier","airbnb"],"env":{"es6":true,"browser":true},"globals":{"API_URL":true},"rules":{"arrow-parens":0,"arrow-body-style":0,"no-extra-semi":2,"no-tabs":0,"react/jsx-filename-extension":0,"react/require-default-props":0,"react/forbid-prop-types":0,"jsx-a11y/click-events-have-key-events":0,"jsx-a11y/no-noninteractive-element-interactions":0}}/* 2. ---- ./package.json file ---- */"scripts":{// ..."lint":"./node_modules/.bin/eslint ./src/app/**/*.js","precommit":"pretty-quick --staged"}

★ Tips:


4. Webpack4 setup and configuration

4.1 - Intro to Webpack "module bundler" and its dependency graph

  • How webpack works
    • Entry point:Starting point of the graph. From here Webpack starts following the importsto form the rest of the graph.
    • Output:Explicit path (where to save the output bundle).
    • Module:Any file, whether a JS file, stylesheet, image, font, Markdown, etc.
    • Loaders:A transformation applied to a module through the bundling process.
    • Plugins:Apply transformations on parts of the bundle output.
    • Simple run from terminal:node_modules/.bin/webpack ./entry-point.js ./output-file.js
  • How to install and configure Webpack: Thewebpack.config.js file.
  • Integrating Babel into webpack using a loader
  • Use ofwebpack-dev-server★ Note: Webpack dev server's cli have moved towebpack-cli in webpack4.
  • Setting up a webpack plugin
  • Getting everything ready to start writing React code.

4.2 - Installations

# Babel core  yarn add -D babel-core babel-cli# Babel main loader for Webpack  yarn add -D babel-loader# Babel presets. Note 'babel-preset-es2015' is deprecated  yarn add -D babel-preset-react babel-preset-env babel-preset-stage-0# Webpack and dev server:  yarn add -D webpack webpack-cli webpack-dev-server# Additional Webpack loaders for html, css, postcss, images and fonts:  yarn add -D html-loader file-loader css-loader style-loader sass-loader node-sass postcss postcss-loader# Webpack plugins for serving html and clean our '/dist' folder:  yarn add -D html-webpack-plugin clean-webpack-plugin# Install React libraries as main dependencies:  yarn add react react-dom react-router-dom prop-types# Install dotenv for global environment variables definitions# Note: 'whatwg-fetch' polyfill is for older browsers 'fetch' support:  yarn add -D dotenv dotenv-webpack whatwg-fetch

4.3 - Configurations

  • → Thewebpack.config.js file.
/* 1. ---- ./config/webpack.dev.js ---- */// Core - Pluginsconstwebpack=require('webpack');constpath=require('path');constDotenv=require('dotenv-webpack');constCleanWebpackPlugin=require('clean-webpack-plugin');constHtmlWebPackPlugin=require('html-webpack-plugin');// Rules - moved to a separate file for readabilityconstappRules=require('./rules.js');// Main directories - change if you move this fileconstrootDir='..';constinDir='src';constoutDir='dist';// Paths - PortsconstPATHS={src:path.join(__dirname,`${rootDir}/${inDir}`),dist:path.resolve(__dirname,`${rootDir}/${outDir}`),serve:path.join(__dirname,`${rootDir}/${outDir}`),servePort:8799,};// Vendors in separate bundleconstvendorLibs=['react','react-dom','react-router-dom','prop-types'];// config() exposes 'env' to 'process.env' (see plugins section)require('dotenv').config();/** * Export main JS Object. We name it CONFIG optionally for modularity. * Here we define the 'entry' and the 'output' values */constCONFIG={/**   * 1. ENTRY POINT   * Here we define the entry and the output key values. Note that webpack 4   * is serving files from an 'src' by default and outputs in 'dist' folder.   * Optional use of 'context' key to define main source path so we can avoid   * writing './src/index.js'   */context:PATHS.src,entry:{bundle:[// Older browsers polyfill support for 'fetch''whatwg-fetch',/**       * For hot reloading into an existing server without webpack-dev-server       * add 'webpack-hot-middleware/client':       */'./index.js',],vendor:vendorLibs,},devtool:'inline-source-map',/**   * 2. DEV-SERVER   * https://webpack.js.org/configuration/dev-server/   */devServer:{/**     * Use historyApiFallback to redirect not found requests to index.html file     * so we can use react-router instead of the build in express server.     * It is a good practice to define 'publicPath' here and also in 'output'     * section (6.)     */historyApiFallback:{index:[`${outDir}/index`],},contentBase:PATHS.serve,watchContentBase:true,publicPath:`/${outDir}/`,port:PATHS.servePort,compress:true,progress:true,open:true,inline:true,hot:true,stats:{colors:true,},},/**   * 4. LOADERS:   * Rules are defined in './config/rules.js' file for readability.   * Inside the rules array we can add as many loaders as we want.   * Every loader takes a 'test' attribute that accepts a regex as a value.   */module:{/** Exclude large libs for performance */// noParse: content => /jquery|lodash/.test(content),rules:[appRules.JS_RULE,appRules.HTML_RULE,appRules.CSS_RULE,appRules.SASS_RULE,appRules.FILE_RULE,appRules.FONT_RULE,],},/**   * 5. PLUGINS   */plugins:[// Clean webpack pluginnewCleanWebpackPlugin([outDir]),/**     * Html plugin     * https://github.com/jantimon/html-webpack-plugin     */newHtmlWebPackPlugin({template:'index.html',favicon:'favicon.ico',inject:'body',}),/** HMR - Native webpack plugins (no need for installation) */newwebpack.NamedModulesPlugin(),newwebpack.HotModuleReplacementPlugin(),newwebpack.LoaderOptionsPlugin({debug:true,}),/**     * Webpack gives our modules and chunks ids to identify them.     * https://github.com/webpack/docs/wiki/optimization:     */newwebpack.optimize.OccurrenceOrderPlugin(),/**     * Use '.env' file for global var definitions, and store sensitive data.     * The '.env.sample' file in this repo that must be renamed to '.env'.     * Read carefully: https://github.com/mrsteele/dotenv-webpack     */newDotenv({path:'./.env',safe:false,systemvars:true,}),/**     * Register global vars to webpack for all the files. Must return a string.     */newwebpack.DefinePlugin({API_URL:JSON.stringify(process.env.API_URL),}),],/**   * 6. OUTPUT   * https://webpack.js.org/configuration/output/   */output:{filename:'[name].js',path:`${PATHS.dist}/`,sourceMapFilename:'[file].map',chunkFilename:'[name].js',publicPath:`/${outDir}/`,},resolve:{extensions:['.js','.json','.css'],},};module.exports=CONFIG;
  • Thepackage.json file. Here we can define our project dependencies, the scripts we want to run, the babel presets, browser support for auto-prefixer and many more...
/**   * 2. ---- ./package.json (scripts section) ----   * Here we can define separate files for production or development  */"scripts":{"serve":"webpack-dev-server --config ./config/webpack.dev.js --mode development","build":"webpack --config ./config/webpack.dev.js --mode production","watch":"webpack --config ./config/webpack.dev.js --watch --mode development","lint":"./node_modules/.bin/eslint ./src/**/*.js","pretty":"./node_modules/.bin/prettier ./src/**/*.js --write","precommit":"pretty-quick --staged"},"babel":{"presets":["react","env"]},"browserslist":["> 1%","last 2 versions"],// ...
  • The.env file. Here we define sensitive data that we want webpack to process but we don't want to leave our machine. It is a good idea to add this file to.gitignore. Inside this repo the.env.sample file must be renamed to.env
# 2. ---- ./env ----API_URL=http://reactrecipes.herokuapp.com

4.4 - Run the project in browser

Rename.env.sample to.env, runyarn serve and watch the server inlocalhost:8799


5. React overview

  • Creating and mounting root component. About renderers.
  • Functional and Class components
  • Importing assets
  • Compose components to create more complex UI
  • Props: Read only data-types (strings, numbers, arrays, objects, classes...)
  • Passing and collecting props, conditionals and common problems
  • Prop-types in React
  • Intro to fetch: A promised based web request mechanism
  • Making async request in the component life cycle
  • Use the state to make components dynamic
  • Basic use ofReact Router v4.x
  • Handling redirects and 404
  • Add links to routes

6. Styling in React

Different approaches, one philosophy: "the real way to scale CSS, is to stop writing CSS". You are using JS anyway, so why not take advantage of the language to style your elements ?

  • Plain CSS:Hard to maintain in large scale. Global naming, monolithic files, high coupling between components.

  • Inline styling:Use of the style prop of React elements.

    • The good: CSS in JS
    • The bad: No reusable CSS. High coupling between markup and styles. Huge components.
  • CSS modules:Treat a CSS file as one module using Webpack

    • The good: Component isolated CSS. No monolithic files with global scope.
    • The bad: No reusable CSS. Huge amount of files.
  • Styled components:CSS in JS solution using ES6.

    • The good: CSS with JS in one file. Easy props based styles. Popular. Good for animation.
    • The bad: Hard to style components with many nested elements.
    • The ugly: Odd backtick syntax. Bloated files.
  • Functional CSS withBassCSS:CSS toolkit with extensible predefined classes: "The overwhelming majority of CSS you would need for your elements has already been written".

    • The good: Almost zero repetition. Enforces style-guide. Quick to prototype. PostCSS and CSSNext. Small(er) bundled file.
    • The bad: Hard to apply specific styles. Find and replace problem. Fixed units.
    • The ugly: Long less semantic classnames. Confusing at first.
  • Worth exploring:

    • Tachyons: Functional css for humans.
    • Radium is a set of tools to manage inline styles on React elements. It gives you powerful styling capabilities without CSS.
    • Aphrodite: Inline Styles that work.
    • Styletron: Universal, high-performance JavaScript styles.
    • React-JSS

6.1 - Setting Up PostCSS

ThePostCSS project is an amazing project that allows CSS transformations using JS. They also claim that PostCSS "transforms CSS specs into more compatible CSS so you don’t need to wait for browser support."You can think thatPostCss is to CSS, what Babel is to JS. It enable us to write CSSNext.CSSNext is to CSS, what ES6 is to JS: Use of future CSS features that are not yet supported by the browser.

Features: Automatic vendor prefixer with autoprefixer, custom properties and var(), nesting, many color functions and more...

★ Tip: There are many (more than 200) powerfulPostCSS plugins, some good learning sources out there and even agithub tutorial byDavid Wells

  • Install Autoprefixer, Postcss and postcss-loader for webpack.

    yarn add -D autoprefixer postcss postcss-loader

  • Add some postcss plugins that will allow us custom PostCSS transformations in basscss. Note thatclassnames library is not a postcss plugin but a very useful CSS utility for React (seeRecipeDetail.js file):

    yarn add -D postcss-cssnext postcss-import classnames

  • Configure css rules in./config/rules.js file:

//.../**       * Css loader - Exclude node_modules       * https://webpack.js.org/loaders/css-loader/       * - The postcss loader has a separate config file in project root.       * - Webpack is reading the order of the plugins from right to left       *   so in this setup "postcss-loader" will be loaded first.      */{test:/\.css$/,exclude:/node_modules/use:["style-loader","css-loader","postcss-loader"],},//...
  • Configure thepostcss.config.js file:
/* 2. ---- Create a ./postcss.config.js file ---- */module.exports={plugins:[require('postcss-cssnext'),require('postcss-import')],};

6.2 - Setting UpBassCSS

  • Install basic libraries. We will install them as main dependencies:

yarn add basscss basscss-background-colors basscss-colors classnames

If your postcss rules are setup correctly you are good to go.


7. Testing with jest and Enzyme

Jest is a fast and sand-boxed JS testing engine that is easy to configure. It is not limited only to React as it can provide tests for all majorweb frameworksJest provides build-in coverage reports, snapshot testing support with automaticBabel integration.

7.1 Install and setup Jest

  • Install Jest and itseslint plugin. Thereact-test-renderer is for snapshot tests later on:

    yarn add jest eslint-plugin-jest react-test-renderer -D

  • By default Jest will create a__test__ folder will include test files according this regex pattern:(/__tests__/.*|\\.(test|spec))\\.(js|jsx)$. If we want a custom one, we create ajest.config.js file inside the folder of our choice. In this case thespecs folder:

    module.exports={// Use a regex pattern to define a test foldertestRegex:'./src/.*?(Spec)\\.js',// Ignored foldersmodulePathIgnorePatterns:['node_modules','dist'],// Ignore __snapshots__ folders for teststestPathIgnorePatterns:['__snapshots__'],};
  • Create a sample test in./src/specs/TestSpec.js:

    /* ---- ./src/specs/TestSpec.js ---- */describe('Test',()=>{test('Test',()=>{// assert});});
  • Edit the./.eslintrc.json file:

    //..."plugins":["jest"],"env":{"es6":true,"browser":true,"jest/globals":true},//...
  • Add a "test" script inpackage.json file and run it:

    //..."test":"./node_modules/.bin/jest",//...

7.2 Use snapshot tests for react components

ThetoMatchSnapshot function is responsible for saving the JSON tree, compares it to the output JSON and checking if it matches.

test('Test Name',()=>{expect(json).toMatchSnapshot();});

This is why we need to transform a component to a JSON representation to createa snapshot test. The oficial tool for creating Jest representations of React components isreact-test-renderer and we must install it.

  • ★ Tip: Notice that because of our setup we need always to add theSpec postfix in the end of the file. So if we need to test theHeader.js component, we must create aHeaderSpec.js test file.
test('Test Name',()=>{constcomponent=renderer.create(<Component/>);consttree=component.toJSON();});

Now we can create our snapshot tests. Some examples can be foundin./specs file.

7.3 Mock Static assets in our tests:

Configuring Jest to mock images on our tests by adding the following lines injest.config.js:

//.../**   * Jest by default will try to load a static asset as a real js package.   * Every time we try to import a module inside a test that matches a regex,   * load a mock file instead of loading the real package.   */moduleNameMapper:{'\\.(jpg|jpeg|png)$':'<rootDir>/src/utils/fileMock.js',},

Then we create./src/utils/fileMock.js file:

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

7.4 UseEnzyme to test more complex scenarios:

Enzyme is a JS utility for React from airbnb, that makes it easier to assert, manipulate and traverse your React component output.It mimics jQuery API for DOM manipulation and traversal. Use it with an Adapter for the particular React version you are using.

  • Enzyme Shallow rendering: Useful for constraining yourself to testing a component as a unit. Renders components only one level down. Accessible via theshallow function

  • Enzyme Full rendering: Ideal for use cases where you have components that may interact with DOM APIs, or may require the full lifecycle callbacks to be executed. Also for testing click events. Accessible via themount function.

Enzyme component wrapper API

  • find(selector): Find nodes that matches the provided selector
  • hasClass(className): Returns whether or not the component has the provided class.
  • exists(): Returns whether or not the current element exists.
  • first(): Returns first node of the current wrapper.
  • last(): Returns last node of the current wrapper.
  • simulate(): Simulates an event on the current node by passing the type of the event that we want to simulate in an argument.
  • setProps(): Manually set props on the root component.
  • setState(): Manually set state on the root component.
  • more ...

Jest-enzyme setup

  • Install Enzyme:yarn add enzyme enzyme-adapter-react-16

  • Create a polyfill for therequestAnimationFrame function browser support in./src/specs/polyfill.js file:

    constrequestAnimationFrame=cb=>{setTimeout(cb,0);};// Assign the above function to the global functionglobal.requestAnimationFrame=requestAnimationFrame;exportdefaultrequestAnimationFrame;
  • Create the ini script for Jest in./src/specs/index.js

    /* eslint-disable */importpolyfillfrom'./polyfill';importEnzymefrom'enzyme';importAdapterfrom'enzyme-adapter-react-16';Enzyme.configure({adapter:newAdapter()});
  • Finally inform jest.config about ini script:

    //...setupFiles:['<rootDir>/src/specs/index.js'],

About

Setup a project with Webpack4 and learn some React concepts along the way

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp