All Projects → LaurenceHo → react-weather-app

LaurenceHo / react-weather-app

Licence: MIT License
☀️🌤⛈❄️A weather web application using React, Redux, Typescript, Webpack, Ant Design, ECharts and firebase.

Programming Languages

CSS
56736 projects
typescript
32286 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to react-weather-app

react-drag
A drag and drop platform based on sortable.js front-end visualization. 一个基于sortable.js的前端可视化搭建的拖拽平台,ui组件采用antd-mobile.通过umi脚手架构建.技术栈采用dva+hooks+umi+antd-mobile+sortable.js+react-color.
Stars: ✭ 51 (-56.41%)
Mutual labels:  antd
antdCascaderDate
202104最新更新,对于antd Cascader 内中国省市区数据的补充,数据基于 2020月12月中华人民共和国县以上行政区划代码,生成此数据的方法:https://github.com/heerey525/antdCascaderDateMethod
Stars: ✭ 158 (+35.04%)
Mutual labels:  antd
antd-curd
📦 基于 ant design 、 dva 、 antd-form-mate 的增删改查页面组件。
Stars: ✭ 26 (-77.78%)
Mutual labels:  antd
blog
个人博客(Junming.Su) Blog 个人博客 喜欢写文章 收藏文章
Stars: ✭ 17 (-85.47%)
Mutual labels:  antd
Deep-Viz-Website
The Deep-Viz Components' display website ( Base on React + Dva + Ant-Design) 组件库Deep-Viz的展示网站
Stars: ✭ 12 (-89.74%)
Mutual labels:  antd
react-admin-template
react + antd + vite/webpack5 后台管理系统模板
Stars: ✭ 73 (-37.61%)
Mutual labels:  antd
dva-typescript-antd-starter-kit
A admin dashboard application demo based on antd by typescript and dva
Stars: ✭ 61 (-47.86%)
Mutual labels:  antd
trackupdates
A simple yaml-based xpath crawler framework for easy tracking site updates. https://zhupeng.github.io/
Stars: ✭ 20 (-82.91%)
Mutual labels:  antd
animaris
Documentation and Mock for JSBridge base on ThinkJS & MongoDB & React & Antd.
Stars: ✭ 28 (-76.07%)
Mutual labels:  antd
GOSH-FHIRworks2020-React-Dashboard
🩺 Fully Responsive FHIR Dashboard written using @reactjs for NHS and GOSH hackathon
Stars: ✭ 21 (-82.05%)
Mutual labels:  antd
fishing-funds
基金,大盘,股票,虚拟货币状态栏显示小应用,基于Electron开发,支持MacOS,Windows,Linux客户端,数据源来自天天基金,蚂蚁基金,爱基金,腾讯证券,新浪基金等
Stars: ✭ 424 (+262.39%)
Mutual labels:  antd
epee-react-admin
🗡简洁、高效、易扩展的 React 快速开发模板,基于布局设计,纯 Hooks 开发,包含中后台应用常用功能
Stars: ✭ 87 (-25.64%)
Mutual labels:  antd
react-vite-admin
This Starter utilizes React, Recoil, React Query, React Hooks, Typescript, Axios And Vite. 全新技术栈的后台管理系统
Stars: ✭ 90 (-23.08%)
Mutual labels:  antd
react-visualized-platform
🐞 基于 React 的雾霾数据爬虫分析平台
Stars: ✭ 31 (-73.5%)
Mutual labels:  antd
react-smart-app
Preconfiguration React + Ant Design + State Management
Stars: ✭ 13 (-88.89%)
Mutual labels:  antd
react-cli
基于 create-react-app 搭建的前端脚手架
Stars: ✭ 18 (-84.62%)
Mutual labels:  antd
react-typescript
A Front-End Project with Typescript/Antd. webpack5+react-router4+antd+typescript4+grahql
Stars: ✭ 63 (-46.15%)
Mutual labels:  antd
pityWeb
🎉一个持续迭代的开源接口测试平台(前端),欢迎大家多提issue多给反馈。 求star⭐,我会努力更新下去的!
Stars: ✭ 25 (-78.63%)
Mutual labels:  antd
parcoords-es
ES6 module of Syntagmatic's Parallel Coordinates
Stars: ✭ 58 (-50.43%)
Mutual labels:  d3v5
gatsby-wordpress-typescript-scss-blog
Gatsby Wordpress Typescript Blog Boilerplate
Stars: ✭ 50 (-57.26%)
Mutual labels:  antd

☀️🌤❄️ A weather web application using React, Redux, TypeScript, Webpack4, Ant Design, ECharts and firebase.

Table of Contents

Introduction

This project demonstrates how to use ReactJS, Redux, TypeScript, Webpack4, Ant Design, D3v5, ECharts and Mapbox. It is also including two kinds of D3 force simulation demonstrations along with gauge, which is based on my personal interest and previous project.

Furthermore, this project also demonstrates how to deploy the web app to Google firebase, and use Google cloud function serverless platform with React frontend app.

Prerequisites

  1. The latest version of Nodejs and npm need to be installed
  2. Google Geocoding API Key
  3. Google Firebase project
  4. Dark Sky weather API key
  5. Windy API key
  6. Mapbox API key

[NOTE] Since I already placed protection to all keys, you cannot use my own key. You have to apply for your own API key.

Local development

  • Clone the repo: git clone https://github.com/LaurenceHo/react-weather-app.git
  • Install npm package: npm i
  • If you want to start client using webpack dev server: npm run start, and visit in your browser: http://localhost:8080.
  • Because we don't want to use Google Cloud Function when we do local development, we write simple NodeJs Express server for returning mock JSON response. Move to dev-server folder cd dev-server, and run npm i to install the npm modules. After that, run npm start to start NodeJs Express Server, and we can move forward to frontend development.
  • Put your Windy API key and Mapbox API key into ./src/constants/api-key.ts
  • For bundling frontend code run npm run build

Back to the top↑

Write Your Own Google Cloud Functions:

Please visit: Google Cloud Functions for more detail

Deploy to Firebase

  • Put your Google Geocoding API Key and dark sky API key into ./functions/apiKey.js.
  • Change the Google Cloud Function URL CLOUD_FUNCTION_URL in api.ts to your own Google Cloud Function URL.
  • Visit https://console.firebase.google.com to create a new project
  • Check here for further detail about how to deploy your app to Firebase
  • If you want to deploy the whole project, run npm run firebase-deploy
  • If you want to deploy the cloud functions only, run npm run deploy-functions

Back to the top↑

Webpack, Reactjs and TypeScript

Although there is create-react-app toolkit to create ReactJS project very easily and quickly, I personally love creating the ReactJS project by using webpack from the beginning. Also configure the project a bit by bit manually. It helps me to understand how these things work together.

When using webpack, we need a bunch of loaders to parse the specific file types. For example, ts-loader for Typescript, css-loader for css files, file-loader for pictures...etc.

Before starting using webpack with TypeScript, we at least need to install the following plugins: npm i -D css-loader file-loader html-webpack-plugin source-map-loader style-loader ts-loader typescript webpack webpack-cli

In the webpack.common.js file, setup the entry point at first:

module.exports = {
  entry: ['./src/index.tsx'],
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: '[name].bundle.js',
  },
  resolve: {
    modules: [path.join(__dirname, '../dist'), 'node_modules'],
    extensions: ['.ts', '.tsx', '.js', '.json'],
  },
}

Then setup the loaders:

{
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: 'ts-loader'
      },
      {
        enforce: 'pre',
        test: /\.js$/,
        exclude: /(node_modules)/,
        loader: 'source-map-loader'
      },
      {
        test: /\.css$/,
        use: [ 'style-loader', 'css-loader' ]
      },
      {
        test: /\.(jpe?g|png|gif|ico)$/i,
        use: [ 'file-loader' ]
      },
      {
        test: /\.(ttf|eot|svg|woff|woff2)(\?.+)?$/,
        loader: 'file-loader?name=[hash:12].[ext]',
      },
    ]
  }
}

If we want to extract CSS into separate files, we need to install mini-css-extract-plugin, and replace style loader:

  {
    test: /\.css$/,
    use: [
      {
        loader: MiniCssExtractPlugin.loader,
        options: {
          hmr: process.env.NODE_ENV === 'development',
        },
      },
      'css-loader',
    ],
  },

Then setup the plugins:

{
  plugins: [
    new HtmlWebpackPlugin({
      template: 'src/index.html'
    }),
    new CopyWebpackPlugin([
      {
        from: 'src/assets',
        to: 'assets'
      }
    ])
  ]
}

Back to the top↑

Webpack Dev Server and Hot Module Replacement

When we do frontend development, we want the browser reloading the content automatically when we make changes. To achieve this, we need WebpackDevServer. So let's install something: npm i -D webpack-dev-server webpack-merge. In the webpack.dev.js, since we want to merge the common setting, we need webpack-merge library along with WebpackDevServer for browser reloading:

const merge = require('webpack-merge');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: {
    contentBase: '../dist',
    historyApiFallback: true,
    hot: true,
    inline: true,
  },
  plugins: [
    new DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('development'),
      },
    }),
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
  ],
});

And place start script in the package.json for starting the webpack dev server:

  "scripts": {
    "start": "webpack-dev-server --config ./config/webpack.dev.js --progress --profile --watch --open"
  }

Back to the top↑

Optimising Application Bundle Size

Finally, let's look into bundling code for production deployment. Since we want to reduce the bundle file size for production as much as possible, we need to install some plugins for helping us: npm i -D terser-webpack-plugin. We also need CleanWebpackPlugin to clean the build folder (dist) before building code, as well as MiniCssExtractPlugin for extracting CSS files. Therefore, in the webpack.prod.js, we use above plugins to bundle code:

const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const merge = require('webpack-merge');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'production',
  plugins: [
    new DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('production'),
      },
    }),
    new MiniCssExtractPlugin({
      filename: '[name].[hash].css',
      chunkFilename: '[id].[hash].css',
    }),
    new CleanWebpackPlugin(),
  ],
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
        styles: {
          name: 'styles',
          test: /\.css$/,
          chunks: 'all',
          enforce: true,
        },
      },
    },
    minimize: true,
    minimizer: [
      new TerserPlugin({
        cache: true,
        parallel: true,
        terserOptions: {
          output: {
            comments: false,
          },
        },
      }),
    ],
  },
});

Back to the top↑

TypeScript, Eslint and Prettier

Since tslint will soon be deprecated in 2019, I use eslint + typescript-eslint + eslint-plugin-react + prettier for linting project. Run npm i -D @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-config-prettier eslint-plugin-prettier eslint-plugin-react prettier

TypeScript ESLint usage

Add @typescript-eslint/parser to the parser field and @typescript-eslint to the plugins section of .eslintrc.json configuration file:

{
  "parser": "@typescript-eslint/parser",
    "plugins": [
      "@typescript-eslint"
    ],
}

Because we use ReactJS, we also need to set the parserOptions property:

{
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    }
  }
}  

Back to the top↑

eslint-plugin-react usage

Append react to the plugins section:

{
  "parser": "@typescript-eslint/parser",
  "plugins": [
    "react",
    "@typescript-eslint"
  ],
}

Indicate the ReactJS version, add settings property:

{
  "settings": {
    "react": {
      "version": "detect"
    }
  }
}

Back to the top↑

Prettier Integrate with Eslint Using eslint-plugin-prettier

Append prettier into plugins section:

{
  "parser": "@typescript-eslint/parser",
  "plugins": [
    "prettier",
    "react",
    "@typescript-eslint"
  ]
}

Turn off the eslint formatting rule:

{
  "extends": [
    "plugin:@typescript-eslint/recommended",
    "plugin:react/recommended",
    "prettier",
    "prettier/@typescript-eslint",
    "prettier/react"
  ],
  "rules": {
    "prettier/prettier": "error"
  }  
}

Append the prettier configuration in the package.json

"prettier": {
    "jsxSingleQuote": true,
    "jsxBracketSameLine": true,
    "printWidth": 120,
    "singleQuote": true,
    "trailingComma": "es5",
    "useTabs": false
}

Back to the top↑

Ant Design

Getting Started

Ant Design React is dedicated to providing a good development experience for programmers. Make sure that you have installed Node.js(> 8.0.0) correctly. Then run npm i antd

Usage

Ant design provides abundant UI components, which means the library size is quite large. I usually only import the component I needed rather than import everything. Import CSS files in the index.tsx:

import 'antd/es/col/style/css';
import 'antd/es/row/style/css';

Import necessary packages e.g in the current-weather.tsx:

import Col from 'antd/es/col';
import Row from 'antd/es/row';

export class CurrentWeather extends React.Component<any, any> {
  render() {
    const { weather, location, timezone, filter } = this.props;

    return (
      <div>
        <Row justify='center' className='current-weather-top'>
          <Col xs={4} sm={4} md={4} lg={3} xl={3}>
          ......
          </Col>
        </Row>
      </div>
    );
  }
}          

Back to the top↑

Customise theme

If we want customise ant design theme, make sure we install less-loader and style-loader at first. In the webpack.common.js, add less-loader for parsing *.less files along with other loaders:

module.exports = {
  rules: [
    {
      test: /\.less$/,
      use: [
        {
          loader: 'style-loader',
        }, 
        {
          loader: 'css-loader', // translates CSS into CommonJS
        }, 
        {
          loader: 'less-loader', // compiles Less to CSS
          options: {
            modifyVars: {
              'primary-color': '#1DA57A',
              'link-color': '#1DA57A',
              'border-radius-base': '2px',
              // or
              'ant-theme-file': "~'your-less-file-path.less'", // Override with less file
            },
            javascriptEnabled: true,
          },
        }
      ],
    },
     // ...other rules
  ],
  // ...other config
}

We can look at here for getting the further detail.

Back to the top↑

TypeScript

  • Don't use @types/antd, as antd provides a built-in ts definition already.

ECharts

Getting Started

npm i echarts -S and npm i -D @types/echarts

Usage

Keep in mind, we only import the packages on demand. So in our TypeScript files, we import ECharts components as below:

// Import the main module of echarts.
import * as echarts from 'echarts/lib/echarts';
// Import line chart.
import 'echarts/lib/chart/line';
// Import components of tooltip, title and toolbox.
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title';
import 'echarts/lib/component/toolbox';

Back to the top↑

Windy API

Since I put the protection for my Windy API, only the allowed domain name can use this API key. Windy API is free, please feel free to apply for a new one for yourself.

Usage

There is no npm package for installing Windy API, so we have to import source in index.html

<head>
    <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
    <script src="https://api4.windy.com/assets/libBoot.js"></script>
</head> 

Windy API v4 was based on Leaflet 1.4, so import leaflet by this way is very important. How to make these 2 JavaScript 3rd party libraries working in TypeScript? We need to declare the definition in TypeScript Declaration File.

declare const windyInit: any;
declare const L: any;

After that, we can use windyInit and L these 2 parameters directly without importing module into TypeScript file. In weather-map.tsx, when we init Windy API, the basic usage it's very simple:

export const WeatherMap: React.FC<any> = () => {
    const renderMap = () => {
        const options = {
            // Required: API key
            key: 'PsLAtXpsPTZexBwUkO7Mx5I',
            // Put additional console output
            verbose: true,
            // Optional: Initial state of the map
            lat: 50.4,
            lon: 14.3,
            zoom: 5,
        }
        windyInit(options, (windyAPI: any) => {
            const { map } = windyAPI;
            L.popup()
            .setLatLng([50.4, 14.3])
            .setContent("Hello World")
            .openOn( map );
        });
    }

    useEffect(() => {
        renderMap();
    }, []);

    render() {
        return (<div id='windy' />);
    }
}

Back to the top↑

Mapbox

Before starting using Mapbox, get an API for your project. Please go to Mapbox for further detail. For JavaScript bundler installation, you can go to here.

Usage

Import source in index.html:

<head>
    <link href='https://api.mapbox.com/mapbox-gl-js/v2.3.1/mapbox-gl.css' rel='stylesheet' />
</head> 

We can now start using mapbox:

mapboxgl.accessToken = 'YOUR_MAPBOX_API_KEY';
const map = new mapboxgl.Map({
    container: 'map', // container id
    style: 'mapbox://styles/mapbox/streets-v11', // stylesheet location
    center: [-74.5, 40], // starting position [lng, lat]
    zoom: 9 // starting zoom
});

Then we can start using Mapbox very easily:

export const Mapbox: React.FC = () => {
    useEffect(() => {
        mapboxgl.accessToken = 'YOUR_MAPBOX_API_KEY';
        const map = new mapboxgl.Map({
            container: 'map', // container id
            style: 'mapbox://styles/mapbox/streets-v11', // stylesheet location
            center: [-74.5, 40], // starting position [lng, lat]
            zoom: 9 // starting zoom
        });
    }, []);

    render() {
        return (<div id='map' style={{width: 900, height: 500}}/>);
    }
}

You can find more examples from here

Back to the top↑

License

This project is licensed under the MIT License - see the LICENSE.md file for details

Screenshot

main

main

covid

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].