Next.js

Next.js

Next.js by ZEIT - The React Framework Production grade React applications that scale. The world's leading companies use Next.js to build static and dynamic websites and web applications.
Code  Geek

Code Geek

1667462595

Spring Boot Tutorial | Full Stack web app using Spring Boot and React

In this Spring Boot tutorial, you will learn Spring Boot full stack with Next Js, Next-Auth js, and Tailwind CSS. Next Js is a Framework for React Library to build front-end apps. For this Spring Boot tutorial, you will learn how to build an API, along with a React application that will consume the API.

🗒 Project Source Code: https://github.com/shabbirdwd53/employee-management-service-tutorial 
🗒 Project Source Code: https://github.com/shabbirdwd53/nextjs-fullstack-app 
🗒 Project Source Code:
UI: https://github.com/shabbirdwd53/facebook-clone 
Backend: https://github.com/shabbirdwd53/facebook-clone-service 

Subscribe: https://www.youtube.com/c/DailyCodeBuffer/featured 

#springboot #react  #next #tailwindcss 

Spring Boot Tutorial | Full Stack web app using Spring Boot and React
Conor  Grady

Conor Grady

1665062040

A Full-stack DApp Starter Built on Ethereum with Next.js

A full stack dApp starter built on Ethereum (Solidity) with Next.js (React)

This repo contains boilerplate code for interacting with a simple smart contract from the client-side using Solidity, React and TailwindCSS.

Prerequisites

Getting Started

Clone This Repo

Use git clone https://github.com/tomhirst/solidity-nextjs-starter.git to get the files within this repository onto your local machine.

Environment Setup

Duplicate .env.example to .env and fill out the HARDHAT_CHAIN_ID environment variable. The port from the example file, if it's free, will be fine in most cases.

Run npm install.

Running The Smart Contract Locally

Compile the ABI for the smart contract using npx hardhat compile.

If you're successful, you'll recieve a confirmation message of:

Compilation finished successfully

And, a src/artifacts folder will be created in your project.

Deploy the smart contract to the local blockchain for testing with npx hardhat node.

If you're successful, you'll be presented with a number of account details in the CLI. Here's an example:

Account #0: 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 (10000 ETH)
Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

Then in a new terminal window, npx hardhat run scripts/deploy.js --network localhost.

If you're successful, you'll get something like the following CLI output:

Greeter deployed to: 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0

Adding A Local Account To MetaMask

Open your MetaMask browser extension and change the network to Localhost 8545.

Next, import one of the accounts by adding its Private Key (for example, 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 to MetaMask.

If you're successful, you should see the a balance resembling something like 10000 ETH in the wallet.

Connecting The Front-End

In .env set the NEXT_PUBLIC_GREETER_ADDRESS environment variable to the address your smart contract was deployed to. For example, 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0.

In a new terminal window, load the front-end with npm run dev. If you want to use an alternate port from 3000, use npm run dev -- --port=1234, or whatever port number you prefer.

Demo'ing The Functionality

Once set up, go to localhost:3000 (or whatever post number you used), to view your dApp in the browser.

Clicking Fetch greeting from the blockchain should bring back a value of Hello world! in the input above. This is the default string passed to the smart contract on first deloy.

To update the greeting value, type something in the input with placeholder Write a new greeting, then click Set new greeting on the blockchain. If you're successful, a MetaMask window will open in your browser. From here you can connect the local account you added earlier and sign the transaction.

Click Fetch greeting from the blockchain again to see the changes you've made.

Editing The Front-End

To modify the front page of your application, edit pages/index.js.

All TailwindCSS classes are available to you.

To lint your front-end code, use npm run lint.

Testing

To test your smart contracts, run npx hardhat test.

A sample test can be found in test/sample-test.js.

Deploying To The Ropsten Test Network

This is a more advanced step after running the smart contract locally.

Up to now, the smart contract has been running on a local blockchain. The next step, is to test how it works on a live test network. We'll do this by deploying to Ropsten.

MetaMask

First, switch your MetaMask network from Localhost 8545 to Ropsten Test Network.

Then, view the account details of your test account. Click Export Private Key. After entering your password, you'll be given a private key. Copy and paste your private key (example, df57089aefbcaf7ba0bc227dafbffa9fc08a93fdc65e1e42214a14efcf23656e) as the value of ROPSTEN_PRIVATE_KEY in .env.

Important: Never expose the private key of an account with real assets inside. Always add private keys as environment variables. Never commit private keys to code.

Infura

Infura is a service that allows developers to connect to Ethereum infrastructure through their API. In this boilerplate, we'll be using Infura to deploy our smart contract to the Ropsten test network.

Sign up for an account if you don't have one already, then create a new Ethereum project. Name your project, then select Ropsten from the endpoints drop down. Save changes.

Copy and paste the URL starting with https and set it as the ROPSTEN_URL value in your .env file.

Obtaining Test ETH

You'll need some test ETH in your wallet for use on Ropsten. Head over to the Ropsten Ethereum Faucet, paste in your wallet account address (for example, 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80) and press Send me test Ether.

In a few minutes, you should see your balance update in MetaMask. This is your test ETH.

Deploying Your Smart Contract To Ropsten

In your terminal enter, npx hardhat run scripts/deploy.js --network ropsten.

If you're successful, you'll get a confirmation message as follows:

Greeter deployed to: 0x9045cEc7161f380C224ae95c15EbE96659A53c46

This address is where your smart contract is deployed on the Ropsten Test Network.

Post deployment, you should also see your ETH decrease a little in MetaMask from the gas transaction fee.

Etherscan

Because your smart contract is now deployed to a live test network, you'll be able to view it's details on Etherscan. Go to Ropsten Etherscan and copy and paste the address you were given in the previous step (for example, 0x9045cEc7161f380C224ae95c15EbE96659A53c46) into the explorer.

You'll be able to see all historical transactions and events here.

Testing The Functionality

Change the NEXT_PUBLIC_GREETER_ADDRESS variable in .env to be the smart contract address on the Ropsten Test Network (for example, 0x9045cEc7161f380C224ae95c15EbE96659A53c46).

Start (or restart) the front-end using npm run dev.

Fetching the greeting from the blockchain will return Hello world! on first run.

Setting a new greeting may take a little longer than it did locally as we're using a real test network.

All instance of setting a new greeting will now create a transaction attached to the smart contract that you can view on Ropsten Etherscan

Roadmap


Download Details:

Author: tomhirst
Source Code: https://github.com/tomhirst/solidity-nextjs-starter

#react #next 

A Full-stack DApp Starter Built on Ethereum with Next.js
Joshua Yates

Joshua Yates

1664183033

Create a Custom Music Player with HTML, CSS & JavaScript

In this tutorial, you'll learn how to create a custom music player with HTML, CSS and JavaScript.

The music player project might seem to be lengthy and complicated at first but I have divided the JavaScript code into 15 easy steps. You can easily create and customize the music player with these 15 steps.

  1. Create Initial References
  2. Create An Array For Song List
  3. Detect If It Is A Touch Device
  4. Format Time
  5. A Function To Set Song
  6. Function To Play Song
  7. Implement Function To Toggle Repeat Mode
  8. Function To Play Next Song
  9. Function To Pause Song
  10. Create Function To Play Previous Song
  11. Function To Toggle Shuffle Mode
  12. Adding Event Listener to Progress Bar
  13. Updating Progress Bar and Time
  14. Function To Create Playlist
  15. Function To Show & Hide Playlist

HTML:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Custom Music Player</title>
    <!-- Font Awesome Icons -->
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css"
      integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g=="
      crossorigin="anonymous"
      referrerpolicy="no-referrer"
    />
    <!-- Google Fonts -->
    <link
      href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&family=Roboto+Mono&display=swap"
      rel="stylesheet"
    />
    <!-- Stylesheet -->
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div class="music-player">
      <button id="playlist">
        <i class="fa-solid fa-angle-down"></i>
      </button>
      <img id="song-image" src="make-me-move.jpg" />
      <div class="song-details">
        <p id="song-name">Make Me Move</p>
        <p id="song-artist">Culture Code</p>
      </div>
      <div class="player-options">
        <button id="shuffle">
          <i class="fa-solid fa-shuffle"></i>
        </button>
        <button id="prev">
          <i class="fa-solid fa-backward-step"></i>
        </button>
        <button id="play">
          <i class="fa-solid fa-play"></i>
        </button>
        <button id="pause" class="hide">
          <i class="fa-solid fa-pause"></i>
        </button>
        <button id="next">
          <i class="fa-solid fa-forward-step"></i>
        </button>
        <button id="repeat">
          <i class="fa-solid fa-repeat"></i>
        </button>
      </div>
      <audio id="audio" preload="metadata"></audio>
      <div id="progress-bar">
        <div id="current-progress"></div>
      </div>
      <div class="time-container">
        <span id="current-time">0:00</span>
        <span id="max-duration">0:00</span>
      </div>
      <div id="playlist-container" class="hide">
        <button id="close-button">
          <i class="fa-solid fa-xmark"></i>
        </button>
        <ul id="playlist-songs"></ul>
      </div>
    </div>
    <!-- Script -->
    <script src="script.js"></script>
  </body>
</html>

CSS:

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}
body {
  height: 100vh;
  background: linear-gradient(to bottom, #2887e3 50%, #16191e 50%);
}
.music-player {
  font-size: 16px;
  width: 80vw;
  max-width: 25em;
  background-color: #ffffff;
  padding: 3em 1.8em;
  position: absolute;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
  border-radius: 0.5em;
  box-shadow: 0.6em 1.2em 3em rgba(0, 0, 0, 0.25);
}
img {
  width: 100%;
  margin-top: 1.25em;
}
#playlist {
  float: right;
}
.song-details {
  font-family: "Poppins", sans-serif;
  text-align: center;
}
.song-details #song-name {
  font-size: 1.3em;
  font-weight: 600;
  letter-spacing: 0.3px;
}
.song-details #song-artist {
  font-size: 0.8em;
}
.player-options {
  display: flex;
  align-items: center;
  justify-content: space-around;
  padding: 0 1.25em;
  margin: 1.25em 0 0.6em 0;
}
.music-player button {
  border: none;
  background-color: transparent;
}
#play,
#pause {
  height: 2.5em;
  width: 2.5em;
  font-size: 1.8em;
  background-color: #2887e3;
  color: #ffffff;
  border-radius: 50%;
}
#prev,
#next {
  color: #16191e;
  font-size: 1.4em;
}
#shuffle,
#repeat {
  color: #949494;
  font-size: 1em;
}
.hide {
  display: none;
}
#progress-bar {
  position: relative;
  width: 100%;
  height: 0.3em;
  background-color: #eeeeee;
  margin: 1em 0;
  border-radius: 0.18em;
  cursor: pointer;
}
#current-progress {
  position: absolute;
  left: 0;
  top: 0;
  display: inline-block;
  height: 100%;
  width: 20%;
  background-color: #2887e3;
  border-radius: 0.18em;
}
.time-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: "Roboto Mono", monospace;
}
#playlist-container {
  background-color: #ffffff;
  position: absolute;
  width: 100%;
  height: 100%;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
  border-radius: 0.6em;
  padding: 2em 1em;
  font-family: "Poppins", sans-serif;
}
#close-button {
  background-color: transparent;
  border: none;
  height: 2em;
  width: 2em;
  cursor: pointer;
  margin-left: 90%;
}
ul {
  list-style-type: none;
}
li {
  display: flex;
  align-items: center;
  margin: 1em 0;
  cursor: pointer;
}
.playlist-song-details {
  margin-left: 1em;
}
.playlist-song-details > span {
  display: block;
}
#playlist-song-artist-album {
  color: #949494;
  font-size: 0.8em;
}
button.active i {
  color: #2887e3;
}
@media screen and (max-width: 450px) {
  .music-player {
    font-size: 14px;
  }
}

.playlist-image-container {
  width: 3em;
}

Javascript:

Lastly, we implement the functionality using javascript. Once again, copy the code below and paste it into your script file. We create the music player in 15 easy steps. These steps are:

  1. Create Initial References
  2. Create An Array For Song List
  3. Detect If It Is A Touch Device
  4. Format Time
  5. A Function To Set Song
  6. Function To Play Song
  7. Implement Function To Toggle Repeat Mode
  8. Function To Play Next Song
  9. Function To Pause Song
  10. Create Function To Play Previous Song
  11. Function To Toggle Shuffle Mode
  12. Adding Event Listener to Progress Bar
  13. Updating Progress Bar and Time
  14. Function To Create Playlist
  15. Function To Show & Hide Playlist
const prevButton = document.getElementById("prev");
const nextButton = document.getElementById("next");
const repeatButton = document.getElementById("repeat");
const shuffleButton = document.getElementById("shuffle");
const audio = document.getElementById("audio");
const songImage = document.getElementById("song-image");
const songName = document.getElementById("song-name");
const songArtist = document.getElementById("song-artist");
const pauseButton = document.getElementById("pause");
const playButton = document.getElementById("play");
const playlistButton = document.getElementById("playlist");
const maxDuration = document.getElementById("max-duration");
const currentTimeRef = document.getElementById("current-time");
const progressBar = document.getElementById("progress-bar");
const playlistContainer = document.getElementById("playlist-container");
const closeButton = document.getElementById("close-button");
const playlistSongs = document.getElementById("playlist-songs");
const currentProgress = document.getElementById("current-progress");

//index for songs
let index;

//initially loop=true
let loop = true;

const songsList = [
  {
    name: "Make Me Move",
    link: "make-me-move.mp3",
    artist: "Culture Code",
    image: "make-me-move.jpg",
  },
  {
    name: "Where We Started",
    link: "where-we-started.mp3",
    artist: "Lost Sky",
    image: "where-we-started.jpg",
  },
  {
    name: "On & On",
    link: "on-on.mp3",
    artist: "Cartoon",
    image: "on-on.jpg",
  },
  {
    name: "Throne",
    link: "throne.mp3",
    artist: "Rival",
    image: "throne.jpg",
  },
  {
    name: "Need You Now",
    link: "need-you-now.mp3",
    artist: "Venemy",
    image: "need-you-now.jpg",
  },
];

//events object
let events = {
  mouse: {
    click: "click",
  },
  touch: {
    click: "touchstart",
  },
};

let deviceType = "";

//Detect touch device

const isTouchDevice = () => {
  try {
    //We try to create TouchEvent(it would fail for desktops and throw error)
    document.createEvent("TouchEvent");
    deviceType = "touch";
    return true;
  } catch (e) {
    deviceType = "mouse";
    return false;
  }
};

//Format time (convert ms to seconds, minutes and add 0 id less than 10)
const timeFormatter = (timeInput) => {
  let minute = Math.floor(timeInput / 60);
  minute = minute < 10 ? "0" + minute : minute;
  let second = Math.floor(timeInput % 60);
  second = second < 10 ? "0" + second : second;
  return `${minute}:${second}`;
};

//set song
const setSong = (arrayIndex) => {
  //this extracts all the variables from the object
  let { name, link, artist, image } = songsList[arrayIndex];
  audio.src = link;
  songName.innerHTML = name;
  songArtist.innerHTML = artist;
  songImage.src = image;
  //display duration when metadata loads
  audio.onloadedmetadata = () => {
    maxDuration.innerText = timeFormatter(audio.duration);
  };
};

//play song
const playAudio = () => {
  audio.play();
  pauseButton.classList.remove("hide");
  playButton.classList.add("hide");
};

//repeat button
repeatButton.addEventListener("click", () => {
  if (repeatButton.classList.contains("active")) {
    repeatButton.classList.remove("active");
    audio.loop = false;
    console.log("repeat off");
  } else {
    repeatButton.classList.add("active");
    audio.loop = true;
    console.log("repeat on");
  }
});

//Next song
const nextSong = () => {
  //if loop is true then continue in normal order
  if (loop) {
    if (index == songsList.length - 1) {
      //If last song is being played
      index = 0;
    } else {
      index += 1;
    }
    setSong(index);

    playAudio();
  } else {
    //else find a random index and play that song
    let randIndex = Math.floor(Math.random() * songsList.length);
    console.log(randIndex);
    setSong(randIndex);
    playAudio();
  }
};

//pause song
const pauseAudio = () => {
  audio.pause();
  pauseButton.classList.add("hide");
  playButton.classList.remove("hide");
};

//previous song ( you can't go back to a randomly played song)
const previousSong = () => {
  if (index > 0) {
    pauseAudio();
    index -= 1;
  } else {
    //if first song is being played
    index = songsList.length - 1;
  }
  setSong(index);
  playAudio();
};

//next song when current song ends
audio.onended = () => {
  nextSong();
};

//Shuffle songs
shuffleButton.addEventListener("click", () => {
  if (shuffleButton.classList.contains("active")) {
    shuffleButton.classList.remove("active");
    loop = true;
    console.log("shuffle off");
  } else {
    shuffleButton.classList.add("active");
    loop = false;
    console.log("shuffle on");
  }
});

//play button
playButton.addEventListener("click", playAudio);

//next button
nextButton.addEventListener("click", nextSong);

//pause button
pauseButton.addEventListener("click", pauseAudio);

//prev button
prevButton.addEventListener("click", previousSong);

//if user clicks on progress bar
isTouchDevice();
progressBar.addEventListener(events[deviceType].click, (event) => {
  //start of progressBar
  let coordStart = progressBar.getBoundingClientRect().left;
  //mouse click position
  let coordEnd = !isTouchDevice() ? event.clientX : event.touches[0].clientX;
  let progress = (coordEnd - coordStart) / progressBar.offsetWidth;

  //set width to progress
  currentProgress.style.width = progress * 100 + "%";

  //set time
  audio.currentTime = progress * audio.duration;

  //play
  audio.play();
  pauseButton.classList.remove("hide");
  playButton.classList.add("hide");
});

//update progress every second
setInterval(() => {
  currentTimeRef.innerHTML = timeFormatter(audio.currentTime);
  currentProgress.style.width =
    (audio.currentTime / audio.duration.toFixed(3)) * 100 + "%";
});

//update time
audio.addEventListener("timeupdate", () => {
  currentTimeRef.innerText = timeFormatter(audio.currentTime);
});

//Creates playlist
const initializePlaylist = () => {
  for (let i in songsList) {
    playlistSongs.innerHTML += `<li class='playlistSong' onclick='setSong(${i})'>
            <div class="playlist-image-container">
                <img src="${songsList[i].image}"/>
            </div>
            <div class="playlist-song-details">
                <span id="playlist-song-name">
                    ${songsList[i].name}
                </span>
                <span id="playlist-song-artist-album">
                    ${songsList[i].artist}
                </span>
            </div>
        </li>`;
  }
};

//display playlist
playlistButton.addEventListener("click", () => {
  playlistContainer.classList.remove("hide");
});

//hide playlist
closeButton.addEventListener("click", () => {
  playlistContainer.classList.add("hide");
});

window.onload = () => {
  //initially first song
  index = 0;
  setSong(index);
  //create playlist
  initializePlaylist();
};

Related Videos

Create Custom Music Player in HTML CSS & JavaScript

Build a Music Player | Vanilla JavaScript

Build a Music Player with HTML CSS & JavaScript

Create A Music Website Using HTML CSS JAVASCRIPT | Add Music In HTML Website

 

#html #css #javascript

Create a Custom Music Player with HTML, CSS & JavaScript
Dexter  Goodwin

Dexter Goodwin

1661883420

Next-optimized-images Auto Optimizes Images Used in Next.js Projects

🌅 next-optimized-images

💡 Version 3 is coming! It introduces a complete rewrite with many new features and bugfixes. If you want to help developing and testing the upcoming major version, please check out the canary branch for installation instructions and more information about the new features. (RFC issue)


Automatically optimize images used in next.js projects (jpeg, png, svg, webp and gif).

Image sizes can often get reduced between 20-60%, but this is not the only thing next-optimized-images does:

  • Reduces image size by optimizing images during build
  • Improves loading speed by providing progressive images (for formats that support it)
  • Inlines small images to save HTTP requests and additional roundtrips
  • Adds a content hash to the file name so images can get cached on CDN level and in the browser for a long time
  • Same image URLs over multiple builds for long time caching
  • Provides query params for file-specific handling/settings
  • jpeg/png images can be converted to webp on the fly for an even smaller size
  • Provides the possibility to use SVG sprites for a better performance when using the same icons multiple times (e.g. in a list)
  • Can resize images or generate different placeholders while lazy loading images: low quality images, dominant colors or image outlines

Installation

npm install next-optimized-images

Node >= 8 is required for version 2. If you need to support older node versions, you can still use version 1 of next-optimized-images.

Enable the plugin in your Next.js configuration file:

// next.config.js
const withPlugins = require('next-compose-plugins');
const optimizedImages = require('next-optimized-images');

module.exports = withPlugins([
  [optimizedImages, {
    /* config for next-optimized-images */
  }],

  // your other plugins here

]);

See the configuration section for all available options.

:warning: From version 2 on, images won't get optimized out of the box anymore. You have to install the optimization packages you really need in addition to this plugin. This doesn't force you to download big optimization libraries you don't even use. Please check out the table of all optional optimization packages.

The example above uses next-compose-plugins for a cleaner API when using many plugins, see its readme for a more detailed example. next-optimized-images also works with the standard plugin api:

// next.config.js
const withOptimizedImages = require('next-optimized-images');

module.exports = withOptimizedImages({
  /* config for next-optimized-images */

  // your config for other plugins or the general next.js here...
});

Optimization Packages

Starting from version 2, you have to install the optimization packages you need in your project in addition to this plugin. next-optimized-images then detects all the supported packages and uses them.

So you only have to install these packages with npm, there is no additional step needed after that.

The following optimization packages are available and supported:

Optimization PackageDescriptionProject Link
imagemin-mozjpegOptimizes JPEG images.Link
imagemin-optipngOptimizes PNG images.Link
imagemin-pngquantAlternative for optimizing PNG images.Link
imagemin-gifsicleOptimizes GIF images.Link
imagemin-svgoOptimizes SVG images and icons.Link
svg-sprite-loaderAdds the possibility to use svg sprites for a better performance. Read the sprite section for more information.Link
webp-loaderOptimizes WebP images and can convert JPEG/PNG images to WebP on the fly (webp resource query).Link
lqip-loaderGenerates low quality image placeholders and can extract the dominant colors of an image (lqip resource query)Link
responsive-loaderCan resize images on the fly and create multiple versions of it for a srcset.
Important: You need to additionally install either jimp (node implementation, slower) or sharp (binary, faster)
Link
image-trace-loaderGenerates SVG image outlines which can be used as a placeholder while loading the original image (trace resource query).Link

Example: If you have JPG, PNG, and SVG images in your project, you would then need to run

npm install imagemin-mozjpeg imagemin-optipng imagemin-svgo

To install all optional packages, run:

npm install imagemin-mozjpeg imagemin-optipng imagemin-gifsicle imagemin-svgo svg-sprite-loader webp-loader lqip-loader responsive-loader jimp image-trace-loader

:warning: Please note that by default, images are only optimized for production builds, not development builds. However, this can get changed with the optimizeImagesInDev config.

:bulb: Depending on your build/deployment setup, it is also possibile to install these as devDependencies. Just make sure that the packages are available when you build your project.

:information_source: Since version 2.5, ico files are also optionally supported but need to be enabled in the handleImages config.

Usage

You can now import or require your images directly in your react components:

import React from 'react';

export default () => (
  <div>
    <img src={require('./images/my-image.jpg')} />
    <img src={require('./images/my-small-image.png')} />
    <img src={require('./images/my-icon.svg')} />
  </div>
);

/**
 * Results in:
 *
 * <div>
 *   <img src="/_next/static/images/my-image-5216de428a8e8bd01a4aa3673d2d1391.jpg" />
 *   <img src="data:image/png;base64,..." />
 *   <img src="/_next/static/images/my-icon-572812a2b04ed76f93f05bf57563c35d.svg" />
 * </div>
 */

Please be aware that images only get optimized in production by default to reduce the build time in your development environment.

If you are using CSS modules, this package also detects images and optimized them in url() values in your css/sass/less files:

.Header {
  background-image: url('./images/my-image.jpg');
}

/**
 * Results in:
 *
 * .Header {
 *   background-image: url('/_next/static/images/my-image-5216de428a8e8bd01a4aa3673d2d1391.jpg');
 * }
 */

If the file is below the limit for inlining images, the require(...) will return a base64 data-uri (data:image/jpeg;base64,...).

Otherwise, next-optimized-images will copy your image into the static folder of next.js and the require(...) returns the path to your image in this case (/_next/static/images/my-image-5216de428a8e8bd01a4aa3673d2d1391.jpg).

You can use both variants directly on an image in the src attribute or in your CSS file inside an url() value.

Query params

If you are using flow or eslint-plugin-import and are experiencing some issues with query params, check out the solution posted by @eleith.

There are some cases where you don't want to reference a file or get a base64 data-uri but you actually want to include the raw file directly into your HTML. Especially for SVGs because you can't style them with CSS if they are in an src attribute on an image.

So there are additional options you can specify as query params when you import the images.

  • ?include: Include the raw file directly (useful for SVG icons)
  • ?webp: Convert a JPEG/PNG image to WebP on the fly
  • ?inline: Force inlining an image (data-uri)
  • ?url: Force an URL for a small image (instead of data-uri)
  • ?original: Use the original image and do not optimize it
  • ?lqip: Generate a low quality image placeholder
  • ?lqip-colors: Extract the dominant colors of an image
  • ?trace: Use traced outlines as loading placeholder
  • ?resize: Resize an image
  • ?sprite: Use SVG sprites

?include

The image will now directly be included in your HTML without a data-uri or a reference to your file.

As described above, this is useful for SVGs so you can style them with CSS.

import React from 'react';

export default () => (
  <div dangerouslySetInnerHTML={{__html: require('./images/my-icon.svg?include')}} />
);

/**
 * Results in:
 *
 * <div>
 *   <svg width="16" height="16" xmlns="http://www.w3.org/2000/svg">
 *     <path d="M8 0C3.589 0 0 3.589 0 8s3.589 ..." style="filled-opacity:1" fill-rule="evenodd">
 *     </path>
 *   </svg>
 * </div>
 */

The image will still get optimized, even if it is directly included in your content (but by default only in production).

?webp

Requires the optional optimization package webp-loader (npm install webp-loader)

WebP is an even better and smaller image format but it is still not that common yet and developers often only receive jpeg/png images.

If this ?webp query parameter is specified, next-optimized-images automatically converts a JPEG/PNG image to the new WebP format.

For browsers that don't yet support WebP, you can also provide a fallback using the <picture> tag:

import React from 'react';

export default () => (
  <picture>
    <source srcSet={require('./images/my-image.jpg?webp')} type="image/webp" />
    <source srcSet={require('./images/my-image.jpg')} type="image/jpeg" />
    <img src={require('./images/my-image.jpg')} />
  </picture>
);

/**
 * Results in:
 * <picture>
 *   <source srcset="/_next/static/images/my-image-d6816ecc28862cf6f725b29b1d6aab5e.jpg.webp" type="image/webp" />
 *   <source srcset="/_next/static/images/my-image-5216de428a8e8bd01a4aa3673d2d1391.jpg" type="image/jpeg" />
 *   <img src="/_next/static/images/my-image-5216de428a8e8bd01a4aa3673d2d1391.jpg" />
 * </picture>
 */

?inline

You can specify a limit for inlining images which will include it as a data-uri directly in your content instead of referencing a file if the file size is below that limit.

You usually don't want to specify a too high limit but there may be cases where you still want to inline larger images.

In this case, you don't have to set the global limit to a higher value but you can add an exception for a single image using the ?inline query options.

import React from 'react';

export default () => (
  <img src={require('./images/my-image.jpg?inline')} />
);

/**
 * Results in:
 *
 * <img src="data:image/png;base64,..." />
 *
 * Even if the image size is above the defined limit.
 */

The inlining will only get applied to exactly this import, so if you import the image a second time without the ?inline option, it will then get normally referenced as a file if it is above your limit.

?url

When you have an image smaller than your defined limit for inlining, it normally gets inlined automatically. If you don't want a specific small file to get inlined, you can use the ?url query param to always get back an image URL, regardless of the inline limit.

If you are using this option a lot, it could also make sense to disable the inlining completely and use the ?inline param for single files.

import React from 'react';

export default () => (
  <img src={require('./images/my-image.jpg?url')} />
);

/**
 * Results in:
 *
 * <img src="/_next/static/images/my-image-5216de428a8e8bd01a4aa3673d2d1391.jpg" />
 *
 * Even if the image size is below the defined inlining limit.
 */

The inlining will only get disabled for exactly this import, so if you import the image a second time without the ?url option, it will then get inlined again if it is below your limit.

?original

The image won't get optimized and used as it is. It makes sense to use this query param if you know an image already got optimized (e.g. during export) so it doesn't get optimized again a second time.

import React from 'react';

export default () => (
  <img src={require('./images/my-image.jpg?original')} />
);

This can also be combined with the ?url or ?inline resource query (e.g. ?original&inline).

?lqip

Requires the optional package lqip-loader (npm install lqip-loader)

When using this resource query, a very small (about 10x7 pixel) image gets created. You can then display this image as a placeholder until the real (big) image has loaded.

You will normally stretch this tiny image to the same size as the real image is, like medium.com does. To make the stretched image look better in chrome, check out this solution and add a blur filter to your image.

import React from 'react';

export default () => (
  <img src={require('./images/my-image.jpg?lqip')} />
);

/**
 * Replaces the src with a tiny image in base64.
 */

?lqip-colors

Requires the optional package lqip-loader (npm install lqip-loader)

This resource query returns you an array with hex values of the dominant colors of an image. You can also use this as a placeholder until the real image has loaded (e.g. as a background) like the Google Picture Search does.

The number of colors returned can vary and depends on how many different colors your image has.

import React from 'react';

export default () => (
  <div style={{ backgroundColor: require('./images/my-image.jpg?lqip-colors')[0] }}>...</div>
);

/**
 * require('./images/my-image.jpg?lqip-colors')
 *
 * returns for example
 *
 * ['#0e648d', '#5f94b5', '#a7bbcb', '#223240', '#a4c3dc', '#1b6c9c']
 */

?trace

Requires the optional package image-trace-loader (npm install image-trace-loader)

With the ?trace resource query, you can generate SVG image outlines which can be used as a placeholder while loading the original image.

import React from 'react';
import MyImage from './images/my-image.jpg?trace';

export default () => (
  <div>
    <img src={MyImage.trace} />   {/* <-- SVG trace */}
    <img src={MyImage.src} />     {/* <-- Normal image which you want to lazy load */}
  </div>
);

/**
 * Results in:
 *
 * <div>
 *  <img src="data:image/svg+xml,...">
 *  <img src="/_next/static/images/image-trace-85bf5c58ce3d91fbbf54aa03c44ab747.jpg">
 * </div>
 */

require('./images/my-image.jpg?trace') returns an object containing the trace (trace) as an inlined SVG and the normal image (src) which also gets optimized.

The trace will have exactly the same width and height as your normal image.

Options for the loader can be set in the plugin configuration.

?resize

Requires the optional package responsive-loader (npm install responsive-loader) and either jimp (node implementation, slower) or sharp (binary, faster)

After the ?resize resource query, you can add any other query of the responsive-loader which allows you to resize images and create whole source sets.

import React from 'react';

const oneSize = require('./images/my-image.jpg?resize&size=300');
const multipleSizes = require('./images/my-image.jpg?resize&sizes[]=300&sizes[]=600&sizes[]=1000');

export default () => (
  <div>
    {/* Single image: */}
    <img src={oneSize.src} />

    {/* Source set with multiple sizes: */}
    <img srcSet={multipleSizes.srcSet} src={multipleSizes.src} />
  </div>
);

If only the size or sizes param is used, the ?resize param can also be omitted (e.g. my-image.jpg?size=300). But it is required for all other parameters of responsive-loader.

You can also set global configs in the responsive property (in the next.config.js file) and define, for example, default sizes which will get generated when you don't specify one for an image (e.g. only my-image.jpg?resize).

?sprite

Requires the optional optimization packages imagemin-svgo and svg-sprite-loader (npm install imagemin-svgo svg-sprite-loader)

If you need to style or animate your SVGs ?include might be the wrong option, because that ends up in a lot of DOM elements, especially when using the SVG in list-items etc. In that case, you can use ?sprite which uses svg-sprite-loader to render and inject an SVG sprite in the page automatically.

import React from 'react';
import MyIcon from './icons/my-icon.svg?sprite';

export default () => (
  <div>
    my page..
    <MyIcon />
  </div>
);

All props passed to the imported sprite will get applied to the <svg> element, so you can add a class normally with <MyIcon className="icon-class" />.

The svg-sprite-loader object also gets exposed if you want to build your own component:

import React from 'react';
import icon from './icons/icon.svg?sprite';

export default () => (
  <div>
    my page..
    <svg viewBox={icon.viewBox}>
      <use xlinkHref={`#${icon.id}`} />
    </svg>
  </div>
);

To also make this work for server-side rendering, you need to add these changes to your _document.jsx file (read here if you don't have this file yet):

// ./pages/_document.js
import Document, { Head, Main, NextScript } from 'next/document';
import sprite from 'svg-sprite-loader/runtime/sprite.build';

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx);
    const spriteContent = sprite.stringify();

    return {
      spriteContent,
      ...initialProps,
    };
  }

  render() {
    return (
      <html>
        <Head>{/* your head if needed */}</Head>
        <body>
          <div dangerouslySetInnerHTML={{ __html: this.props.spriteContent }} />
          <Main />
          <NextScript />
        </body>
      </html>
    );
  }
}

Configuration

This plugin uses img-loader under the hood which is based on mozjpeg, optipng, gifsicle and svgo.

The default options for these optimizers should be enough in most cases, but you can overwrite every available option if you want to.

handleImages

Type: string[]
Default: ['jpeg', 'png', 'svg', 'webp', 'gif']

next-optimized-images registers the webpack loader for all these file types. If you don't want one of these handled by next-optimized-images because you, for example, have another plugin or custom loader rule, simply remove it from the array.

Please note that an image being handled does not mean it also gets automatically optimized. The required optimization package for that image also has to be installed. Please read the optimization packages section for more information.

If an image gets handled but not optimized, it means that the original image will get used and copied for the build.

:information_source: Since version 2.5, ico files are also supported but for backwards compatibility, they need to be manually enabled. By adding 'ico' to the handleImages array, the plugin will also handle ico files.

inlineImageLimit

Type: number
Default: 8192

Smaller files will get inlined with a data-uri by url-loader. This number defines the maximum file size (in bytes) for images to get inlined. If an image is bigger, it will get copied to the static folder of next.

Images will get optimized in both cases.

To completely disable image inlining, set this value to -1. You will then always get back an image URL.

imagesFolder

Type: string
Default: 'images'

Folder name inside /static/ in which the images will get copied to during build.

imagesPublicPath

Type: string
Default: `/_next/static/${imagesFolder}/`

The public path that should be used for image URLs. This can be used to serve the optimized image from a cloud storage service like S3.

From version 2 on, next-optimized-images uses the assetPrefx config of next.js by default, but you can overwrite it with imagesPublicPath specially for images.

imagesOutputPath

Type: string
Default: `static/${imagesFolder}/`

The output path that should be used for images. This can be used to have a custom output folder.

imagesName

Type: string
Default: '[name]-[hash].[ext]'

The filename of the optimized images. Make sure you keep the [hash] part so they receive a new filename if the content changes.

removeOriginalExtension

Type: boolean
Default: false

When images converted to WebP on the fly, .webp was append to the filename. For example, test.png became test.png.webp. If you want to have only one filename extension like test.webp, you can set this option to true.

optimizeImagesInDev

Type: boolean
Default: false

For faster development builds and HMR, images will not get optimized by default when running in development mode. In production, images will always get optimized, regardless of this setting.

mozjpeg

Requires the optional optimization package imagemin-mozjpeg (npm install imagemin-mozjpeg)

Type: object
Default: {}

mozjpeg is used for optimizing jpeg images. You can specify the options for it here. The default options of mozjpeg are used if you omit this option.

optipng

Requires the optional optimization package imagemin-optipng (npm install imagemin-optipng)

Type: object
Default: {}

optipng is used for optimizing png images by default. You can specify the options for it here. The default options of optipng are used if you omit this option.

pngquant

Requires the optional optimization package imagemin-pngquant (npm install imagemin-pngquant)

Type: object
Default: {}

pngquant is an alternative way for optimizing png images. The default options of pngquant are used if you omit this option.

gifsicle

Requires the optional optimization package imagemin-gifsicle (npm install imagemin-gifsicle)

Type: object
Default:

{
    interlaced: true,
    optimizationLevel: 3,
}

gifsicle is used for optimizing gif images. You can specify the options for it here. The default options of gifsicle are used if you omit this option.

svgo

Requires the optional optimization package imagemin-svgo (npm install imagemin-svgo)

Type: object
Default: {}

svgo is used for optimizing svg images and icons. You can specify the options for it here. The default options of svgo are used if you omit this option.

Single svgo plugins can get disabled/enabled in the plugins array:

{
  svgo: {
    plugins: [
      { removeComments: false }
    ]
  }
}

svgSpriteLoader

Requires the optional optimization packages imagemin-svgo and svg-sprite-loader (npm install imagemin-svgo svg-sprite-loader)

Type: object
Default:

{
  runtimeGenerator: require.resolve(path.resolve('node_modules', 'next-optimized-images', 'svg-runtime-generator.js')),
}

When using the svg sprite option, svg-sprite-loader gets used internally. You can overwrite the configuration passed to this loader here.

webp

Requires the optional optimization package webp-loader (npm install webp-loader)

Type: object
Default: {}

imagemin-webp is used for optimizing webp images and converting other formats to webp. You can specify the options for it here. The default options of imagemin-webp are used if you omit this option.

imageTrace

Requires the optional package image-trace-loader (npm install image-trace-loader)

Type: object
Default: {}

When using image-trace-loader for the ?trace resource query, you can define all options for the image trace loader in this object. The default options of image-trace-loader are used if you omit this option.

responsive

Requires the optional optimization package responsive-loader (npm install responsive-loader)

Type: object
Default: {}

The configuration for the responsive-loader can be defined here.

defaultImageLoader

Requires the optional optimization package responsive-loader (npm install responsive-loader)

Type: string
Default: 'img-loader'

By default, img-loader handles most of the requests. However, if you use the responsive-loader a lot and don't want to add the ?resize query param to every require, you can set this value to 'responsive-loader'.

After that, responsive-loader will handle all JPEG and PNG images per default, even without an additional query param. Just be aware that you can't use any of the query params next-optimized-images provides anymore on these images because the request just gets forwarded and not modified anymore. All other formats (SVG, WEBP and GIF) still work as before with the img-loader and so have all query params available.

optimizeImages

Type: boolean
Default: true

If you don't have any optimization package installed, no image will get optimized. In this case, a warning gets written to the console during build to inform you about a possible misconfiguration. If this config is intended and you indeed don't want the images to be optimized, you can set this value to false and you won't get the warning anymore.

Example

The options specified here are the default values.

So if they are good enough for your use-case, you don't have to specify them to have a shorter and cleaner next.config.js file.

// next.config.js
const withPlugins = require('next-compose-plugins');
const optimizedImages = require('next-optimized-images');

module.exports = withPlugins([
  [optimizedImages, {
    // these are the default values so you don't have to provide them if they are good enough for your use-case.
    // but you can overwrite them here with any valid value you want.
    inlineImageLimit: 8192,
    imagesFolder: 'images',
    imagesName: '[name]-[hash].[ext]',
    handleImages: ['jpeg', 'png', 'svg', 'webp', 'gif'],
    removeOriginalExtension: false,
    optimizeImages: true,
    optimizeImagesInDev: false,
    mozjpeg: {
      quality: 80,
    },
    optipng: {
      optimizationLevel: 3,
    },
    pngquant: false,
    gifsicle: {
      interlaced: true,
      optimizationLevel: 3,
    },
    svgo: {
      // enable/disable svgo plugins here
    },
    webp: {
      preset: 'default',
      quality: 75,
    },
  }],
]);

See also

  • next-images if you just want images and not optimize them
  • next-compose-plugins for a cleaner plugins API when you have many plugins in your next.config.js file
  • next-plugins for a list of official and community made plugins

Download Details:

Author: cyrilwanner
Source Code: https://github.com/cyrilwanner/next-optimized-images 
License: MIT 

#javascript #next #images #react 

Next-optimized-images Auto Optimizes Images Used in Next.js Projects
Dexter  Goodwin

Dexter Goodwin

1661859915

Next.js App Work Offline using Service Workers Via Google's Workbox

next-offline

Use Workbox with Next.js and easily enable offline functionality in your application!

Installation

$ npm install --save next-offline
$ yarn add next-offline

Usage

There are two important things to set up, first we need next-offline to wrap your next config.

If you haven't yet, create a next.config.js in your project.

// next.config.js
const withOffline = require('next-offline')

const nextConfig = {
  ...
}

module.exports = withOffline(nextConfig)

Next we need to make sure our application is properly serving the service worker, this setup depends on how you're hosting your application. There is documentation below. If you're not using Now 2.0, the Now 1.0 example should work in most circumstances.

Serving service worker

Because service workers are so powerful, the API has some restrictions built in. For example, service workers must be served on the domain they're being used on - you can't use a CDN.

Now 1.0

You'll want to use the next.js custom server API. The easiest way to do that is creating a server.js that looks like this:

const { createServer } = require('http')
const { join } = require('path')
const { parse } = require('url')
const next = require('next')

const app = next({ dev: process.env.NODE_ENV !== 'production' })
const handle = app.getRequestHandler()

app.prepare()
  .then(() => {
    createServer((req, res) => {
      const parsedUrl = parse(req.url, true)
      const { pathname } = parsedUrl

      // handle GET request to /service-worker.js
      if (pathname === '/service-worker.js') {
        const filePath = join(__dirname, '.next', pathname)

        app.serveStatic(req, res, filePath)
      } else {
        handle(req, res, parsedUrl)
      }
    })
    .listen(3000, () => {
      console.log(`> Ready on http://localhost:${3000}`)
    })
  })

You can read more about custom servers in the Next.js docs

If you're not hosting with Now, I'd probably follow the Now 1.0 approach because the custom server API can enable a lot of functionality, it just simply doesn't work well with Now 2.0 🙇‍♂️

Now 2.0

Because Now 2.0 works so different than the previous version, so does serving the service worker. There are a few different ways to do this, but I'd recommend checking out this now2 example app. The changes to be aware of are in the now.json and next.config.js.

Registering service worker

Compile-time registration

By default next-offline will register a service worker with the script below, this is automatically added to your client side bundle once withOffline is invoked.

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function () {
    navigator.serviceWorker.register('/service-worker.js', { scope: '/' }).then(function (registration) {
      console.log('SW registered: ', registration)
    }).catch(function (registrationError) {
      console.log('SW registration failed: ', registrationError)
    })
  })
}

Runtime registration

Alternative to compile-time, you can take control of registering/unregistering in your application code by using the next-offline/runtime module.

import { register, unregister } from 'next-offline/runtime'

class App extends React.Component {
  componentDidMount () {
    register()
  }
  componentWillUnmount () {
    unregister()
  }
  ..
}

You can choose to pass the service worker path and scope if needed.

import { register, unregister } from 'next-offline/runtime'

class App extends React.Component {
  componentDidMount () {
    /** 
      * Default service worker path is '/service-worker.js' 
      * Refer https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register for default scope rules
      *
    */
    register('/sub_folder/service-worker.js', {scope: '/sub_folder'}) 
  }
  componentWillUnmount () {
    unregister()
  }
  ..
}

If you're handling registration on your own, pass dontAutoRegisterSw to next-offline.

// next.config.js
const withOffline = require('next-offline')

module.exports = withOffline({ dontAutoRegisterSw: true })

Customizing service worker

Using workbox

If you're new to workbox, I'd recommend reading this quick guide -- anything inside of workboxOpts will be passed to workbox-webpack-plugin.

Define a workboxOpts object in your next.config.js and it will gets passed to workbox-webpack-plugin. Workbox is what next-offline uses under the hood to generate the service worker, you can learn more about it here.

// next.config.js
const withOffline = require('next-offline')

const nextConfig = {
  workboxOpts: {
    ...
  }
}

module.exports = withOffline(nextConfig)

next-offline options

On top of the workbox options, next-offline has some options built in flags to give you finer grain control over how your service worker gets generated.

NameTypeDescriptionDefault
generateSwBooleanIf false, next-offline will not generate a service worker and will instead try to modify the file found in workboxOpts.swSrc using WorkBox's [Inject Plugin](https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin#injectmanifest_plugin)true
dontAutoRegisterSwBooleanIf true, next-offline won't automatically push the registration script into the application code. This is required if you're using runtime registration or are handling registration on your own.false
devSwSrcStringPath to be registered by next-offline during development. By default next-offline will register a noop during developmentfalse
generateInDevModeBooleanIf true, the service worker will also be generated in development mode. Otherwise the service worker defined in devSwSrc will be used.false
registerSwPrefixStringIf your service worker isn't at the root level of your application, this can help you prefix the path. This is useful if you'd like your service worker on foobar.com/my/long/path/service-worker.js. This affects the [scope](https://developers.google.com/web/ilt/pwa/introduction-to-service-worker#registration_and_scope) of your service worker.false
scopeStringThis is passed to the automatically registered service worker allowing increase or decrease what the service worker has control of."/"

Cache strategies

By default next-offline has the following blanket runtime caching strategy. If you customize next-offline with workboxOpts, the default behaviour will not be passed into workbox-webpack-plugin. This article is great at breaking down various different cache recipes.

{
  runtimeCaching: [
    {
      urlPattern: /^https?.*/,
      handler: 'NetworkFirst',
      options: {
        cacheName: 'offlineCache',
        expiration: {
          maxEntries: 200
        }
      }
    }
  ]
}
// next.config.js
const withOffline = require('next-offline')

module.exports = withOffline({
  workboxOpts: {
    runtimeCaching: [
      {
        urlPattern: /.png$/,
        handler: 'CacheFirst'
      },
      {
        urlPattern: /api/,
        handler: 'NetworkFirst',
        options: {
          cacheableResponse: {
            statuses: [0, 200],
            headers: {
              'x-test': 'true'
            }
          }
        }
      }
    ]
  }
})

Service worker path

If your application doesn't live on the root of your domain, you can use registerSwPrefix. This is helpful if your application is on domain.com/my/custom/path because by default next-offline assumes your application is on domain.com and will try to register domain.com/service-worker.js. We can't support using assetPrefix because service workers must be served on the root domain. For a technical breakdown on that limitation, see the following link: Is it possible to serve service workers from CDN/remote origin?

By default next-offline will precache all the Next.js webpack emitted files and the user-defined static ones (inside /static) - essentially everything that is exported as well.

If you'd like to include some more or change the origin of your static files use the given workbox options:

workboxOpts: {
  modifyURLPrefix: {
    'app': assetPrefix,
  },
  runtimeCaching: {...}
}

Development mode

By default next-offline will add a no-op service worker in development. If you want to provide your own pass its filepath to devSwSrc option. This is particularly useful if you want to test web push notifications in development, for example.

// next.config.js
const withOffline = require('next-offline')

module.exports = withOffline({
  devSwSrc: '/path/to/my/dev/service-worker.js'
})

You can disable this behavior by setting the generateInDevMode option to true.

next export

In next-offline@3.0.0 we've rewritten the export functionality to work in more cases, more reliably, with less code thanks to some of the additions in Next 7.0.0!

You can read more about exporting at Next.js docs but next offline should Just Work™️.

next offline 5.0

If you're upgrading to the latest version of next-offline I recommend glancing at what's been added/changed inside of Workbox in 5.x releases along with the 4.0 release which included the breaking changes. Next Offline's API hasn't changed, but a core dependency has!


Questions? Feedback? Please let me know

Contributing

next-offline is a lerna monorepo which uses yarn workspaces. After cloning the repo, run the following

$ yarn bootstrap

This will ensure your development version of next-offline is symlinked in the examples & tests which should allow you to quickly make changes!

Download Details:

Author: Hanford
Source Code: https://github.com/hanford/next-offline 
License: MIT

#javascript #next #website #pwa 

Next.js App Work Offline using Service Workers Via Google's Workbox

A Complete NextJS Tutorial on ReactJS Framework

#react #next #java 

In the development world, we all have heard about NextJS, one of the easiest and most compatible frameworks in order to work with ReactJS.


In this tutorial, we are going to take a deep dive into Nextjs in order to understand ReactJS in a better way. First of all, let's understand what exactly NextJS features look like,

  1. Static exporting options
  2. Server-side rendering
  3. Automatic code-splitting
  4. Easy production builds

Our primary goal of this tutorial is to Create NextJS App and Pages and Basic Routing.

In order to understand how NextJS can be beneficial to you checkout this latest tutorial on Nextjs tutorial with reactjs framework 








 

Iara  Simões

Iara Simões

1660665600

11 Coisas A Serem Lembradas Para O Seu Próximo Projeto Flutter

Criar um novo projeto Flutter é uma bênção - base de código nova, nenhum código legado (ainda), segurança nula, versões mais recentes de seus pacotes favoritos e assim por diante. Mas, ao mesmo tempo, você deve tomar decisões críticas no início do projeto que estabeleceriam as bases para o futuro, como ferramentas, pacotes, estrutura de arquivos, solução de gerenciamento de estado, plano de teste. Caso contrário, o projeto acabaria se transformando em apenas mais uma tigela de espaguete e almôndegas. Para evitar isso, preparei uma lista, na minha opinião, dos elementos mais importantes do projeto que devem ser decididos logo no início. Espero que ajude você, portanto - boa leitura!

1. Análise de código estático

Eu não vou escrever código confuso ( fonte )

O Linter é uma ferramenta de análise estática que identifica e sinaliza erros de programação, avisos, falhas de estilo em seu código para você corrigi-los. No contexto do Flutter, essa é uma das coisas mais fáceis de implementar e uma das mais úteis para manter seu código limpo.

Existem várias regras diferentes que você pode definir para o seu código seguir, mas eu recomendaria usar um dos conjuntos predefinidos que já seguem as melhores práticas baseadas no Guia de Estilo do Dart :

Qualquer que seja o pacote escolhido, você sempre pode adicionar ou remover qualquer regra de análise estática específica no arquivo analysis_options.yaml .

2. Localização (l10n)

Localização ( fonte )

O que é localização ( l10n , em suma)?

Localização é a adaptação de um produto ou serviço para atender às necessidades de uma determinada língua, cultura ou “look-and-feel” de uma população desejada. — Tech Target

É essencial construir um aplicativo que pareça natural para os usuários, por exemplo, usando as traduções corretas, formatos de data e moeda, direção do texto. Para isso, a localização é uma ferramenta fundamental a ser utilizada. Mesmo que você esteja criando um único aplicativo de região/idioma, eu ainda recomendo que você implemente a localização desde o início, separando assim seus textos do código da interface do usuário. Consequentemente, eles podem ser reutilizados e ajustados posteriormente sem afetar o código.

A documentação do Flutter explica perfeitamente o processo de internacionalização do seu aplicativo. Se a maneira padrão parecer muito complexa e/ou você precisar de algumas extensões e métodos auxiliares úteis, existem pacotes populares de terceiros, como easy_localization , que podem ajudá-lo no processo de localização.

3. Ambientes (com alguns sabores)

Ambientes de programação ( fonte )

Aposto que você já ouviu pelo menos um caso do seu ambiente (sem trocadilhos) quando alguém corrompeu dados ou excluiu toda a tabela de usuários em produção. Confie em mim - isso não é divertido. Portanto, é uma boa prática criar ambientes diferentes para o seu projeto:

  • Ambiente de desenvolvimento (local) — usado para você enlouquecer: faça experimentos no código, altere dados diretamente no banco de dados, use atalhos e codifique o token de autenticação ou forneça dados simulados. Divirta-se e entregue esses recursos!
  • Um ambiente intermediário ( testing ou staging ) — ajuda você a validar as alterações no código, testar recursos com os dados “reais” (geralmente, um instantâneo dos dados de produção é usado em tais ambientes) e verificar o aplicativo antes de liberá-lo para produção . Se você tem engenheiros de controle de qualidade em sua equipe, este é o lugar para eles brilharem.
  • Ambiente de produção — aquele que é usado por usuários reais, onde a corrupção de dados não é aceitável (sempre faça backups, por favor).

Ter esses ambientes ajuda você a experimentar e verificar recursos com segurança antes que essas alterações cheguem às mãos dos usuários.

Agora, outra parte – sabores . Não, não, não estamos falando de algo doce, salgado ou azedo - esse é apenas mais um termo usado em programação para descrever diferentes variantes de compilação para seu aplicativo. Por exemplo, você deseja que o ícone e o título, o endpoint da API ou qualquer outra configuração sejam diferentes para cada ambiente específico. Para isso, você define um “sabor” diferente que é usado quando o aplicativo está sendo construído para um ambiente específico. Aqui estão alguns recursos sobre como criar sabores para o Flutter .

4. Integração Contínua e Entrega Contínua (CI/CD)

Etapas de Integração Contínua (CI) e Entrega Contínua (CD) ( fonte )

Após a introdução de diferentes ambientes, o próximo passo natural é automatizar o processo de construção, teste e liberação de seu aplicativo. CI/CD é um tópico bastante complexo por si só e eu não sou um especialista neste campo de forma alguma, portanto, eu recomendaria procurar alguns outros recursos sobre como automatizar diferentes estágios de desenvolvimento de aplicativos.

No entanto, existem muitas soluções NoOps compatíveis com o Flutter para que você possa automatizar seu processo de desenvolvimento com facilidade:

Qualquer uma dessas soluções faria o truque - basta selecionar aquela que se adapta às suas necessidades e orçamento.

5. Código de back-end

Uma vez outro meme sobre backend ( source )

Você já tem seu backend implementado em alguma linguagem de programação exótica ou talvez não tão sofisticada? Ótimo, você pode pular esta etapa, mas eu ainda recomendaria verificar algumas soluções em nuvem para referência futura.

Na versão simplificada, há duas opções para a parte de back-end do seu aplicativo:

  1. Implementar uma solução de back-end personalizada usando qualquer linguagem de programação e estrutura que você goste, mas depois cuidar de todas as coisas de DevOps para tornar seu código e dados acessíveis a partir do aplicativo.
  2. Usar qualquer solução em nuvem para acelerar o processo de desenvolvimento e deixar a maior parte do trabalho de DevOps para o provedor de nuvem.

Caso a segunda opção pareça atraente para você, existem algumas ótimas plataformas de nuvem para escolher com suporte ao Flutter:

As plataformas de nuvem fornecem autenticação, banco de dados, armazenamento, opções de API para seu aplicativo e muitos outros recursos. Qualquer uma dessas é uma ótima opção quando você só precisa validar a ideia e construir o MVP rapidamente sem gastar muito tempo na solução de back-end completa.

6. Registro, dados de falhas e análises

Ops, algo deu errado ( fonte )

O registro é subestimado – aqui, eu disse isso! Tudo está legal até que algo dê errado e você precise de informações sobre isso. Há sempre uma área cinzenta quando discutimos o que deve ser registrado e o que não deve ser registrado. Mas uma coisa é sempre clara - você deve saber quando seu aplicativo falha e o que causa o problema. Quanto mais dados você coletar sobre o incidente, mais fácil será encontrar e corrigir o problema.

Serviços como Sentry , Firebase Crashlytics , Datadog podem ajudá-lo a registrar os dados mais importantes, relatórios de falhas ou até mesmo configurar notificações quando seu aplicativo ou serviços relacionados estiverem inativos.

Outro tipo de registro é a coleta de dados do usuário para fins de análise. Quando você está construindo um produto novo, talvez único, é crucial entender as necessidades de seus usuários, seu comportamento e como eles estão usando o aplicativo. Para isso, várias ferramentas de análise podem ser integradas ao seu aplicativo Flutter, como Firebase Analytics , App Center Analytics e muito mais.

7. Marca do aplicativo

Tema do material ( fonte )

Um dos principais objetivos de qualquer aplicativo ou marca é ser reconhecível. Usar a paleta de cores, o logotipo, os ícones, os elementos de design, o conteúdo, a fonte e às vezes até o layout corretos faz com que seu produto se destaque dos demais. Isso é a marca do aplicativo , e preparar as partes fundamentais no início economizará muito tempo durante todo o projeto.

Se você já tem seu protótipo de interface do usuário ou componentes de design prontos, agora é um bom momento para transferi-los para seu aplicativo e definir temas - cores, fontes, formas, etc. Para facilitar, Mike Rydstrom criou um pacote excelente para este — flex_color_scheme .

8. Estrutura do projeto e gestão do estado

Gerenciamento de estado no Flutter ( fonte )

Sim, o polêmico. Só para deixar claro, não existe “a melhor solução de gerenciamento de estado” ou “a melhor arquitetura do aplicativo” – se alguém disser o contrário, lembre-se de que provavelmente também despeja o leite na tigela antes do cereal. E essa é a pior parte - eu não posso te ensinar a melhor maneira. Só posso fornecer várias opções ou compartilhar minhas preferências.

Várias opções de estrutura de arquivos para o próximo projeto Flutter:

  • Arquitetura Limpa — separação clara de interesses, existe há muito tempo. Sinceramente, não sou fã disso. Eu sinto que há muita abstração neste conceito que poderia retardar o processo de desenvolvimento.
  • Arquitetura em camadas — baseia-se na ideia de dividir dados, negócios e lógica de apresentação em camadas separadas. Essa estrutura de arquivos funciona bem para projetos de pequeno a médio porte, mas sinto que essas camadas se tornam cada vez mais esmagadoras à medida que o projeto cresce.
  • Arquitetura Modular (descrevi este conceito aqui ) — dividindo o código em módulos por recurso, onde diferentes módulos interagem. Este é o meu favorito - funciona sem problemas com a solução de gerenciamento de estado BLoC (TEAM BLOC, YEAH!), dimensiona bem para grandes projetos. No entanto, traz alguns desafios, como onde colocar a lógica comum, como os diferentes módulos devem se comunicar e assim por diante.

Sobre a gestão estadual em Flutter — acho que estamos no ponto em que poderíamos dedicar toda a conferência a esse tópico e ainda não ter uma resposta final depois. Apenas para adicionar meus dois centavos, escolha aquele com o qual você se sente mais confortável. Você pode encontrar uma lista abrangente de opções aqui .

9. Geração de código

Geração de código ( fonte )

Se você quiser cortar alguns cantos e economizar algum tempo de desenvolvimento, você pode usar a geração de código em seu projeto. Codifique menos, entregue mais !

Há uma variedade de ferramentas diferentes para usar, seja trabalhando com localizações, ativos, analisando JSON, gerando classes de modelo, implementando localizador de serviços, roteamento ou trabalhando com estados imutáveis. A única coisa a fazer é investigar as ferramentas e pacotes disponíveis e escolher os melhores para cobrir as necessidades do seu projeto.

Para um início rápido do projeto Flutter, eu recomendaria verificar o Very Good CLI . Isso economizaria várias horas de configuração (infelizmente, aprendi da maneira mais difícil).

Além disso, no mês passado eu dei uma palestra sobre geração de código — pode ser um ponto de partida para sua jornada de geração de código Flutter, então confira!

10. Estratégia de teste

Teste de aplicativos ( fonte )

É bom ou ruim cobrir 100% do seu código com testes? Claro, é incrível, mas a que custo? Pensando dessa forma, você pode cair no poço condenado onde você gasta mais tempo escrevendo testes do que desenvolvendo recursos. Para evitar isso, você precisa de uma estratégia de teste.

Não me entenda mal — cobrir seu código com testes é ótimo e quanto mais lugares obscuros do seu código forem cobertos, mais seguro você se sentirá ao implementar novos recursos. Apenas, na minha opinião, você deve encontrar o equilíbrio onde os testes ainda trazem mais valor em comparação com o tempo gasto em escrevê-los. Por exemplo, esta é a minha estratégia de teste:

  • A lógica de negócios (serviços, repositórios, BLoCs) deve ser coberta de 85 a 100% em testes de unidade/integração — essa é a parte mais importante de qualquer aplicativo, então vejo muito valor nos testes;
  • Os testes de widget devem abranger todos os componentes de interface do usuário reutilizáveis. Quando os componentes individuais são testados corretamente, você pode começar a testar telas individuais, mas com menos detalhes.
  • Testes de ponta a ponta , abrangendo os principais fluxos de aplicativos e interações com a interface do usuário. Nenhuma mágica de nível profundo - apenas passando por alguns fluxos de trabalho cruciais. Quanto mais telas eles incluirem, melhor.
  • Quando toda a interface do usuário estiver pronta e implementada — testes de ouro para garantir que a interface do usuário não seja afetada por alterações posteriores.

Honestamente, ainda estou procurando essa média de ouro nos testes, mas você fica melhor nisso projeto após projeto, confie em mim.

11. Arquivo LEIA-ME

Faça um README ( fonte )

Você me ouviu direito - documentação. O arquivo README é o documento mais importante do projeto, principalmente quando se trabalha em equipe.

Você acabou de introduzir uma nova solução que requer geração de código? Você acabou de adicionar um novo script bash útil para automatizar o processo? Você implementou um registrador global que DEVE ser usado em todos os lugares do projeto? Não podemos ler sua mente - mencione isso no arquivo README!

Não existe muita documentação (pelo menos eu não estive em tal situação), apenas a falta de informações sobre o projeto e o código. Todos os comandos para gerar, testar e executar o código, várias decisões de estrutura de arquivos, diagramas, ferramentas e serviços externos, informações sobre diferentes ambientes (SEM CHAVES SECRETAS) devem ser colocados aqui e mantidos em um único local. Este é um trabalho chato, mas muito gratificante!

 

Ufa, que passeio… ( fonte )

É isso! Obrigado pelo seu tempo lendo este artigo.

Perdi alguma coisa? Mencione isso nos comentários! Qual é a sua lista de verificação ao criar um novo aplicativo Flutter?

Fonte: https://medium.com/flutter-community/11-things-to-remember-for-your-next-flutter-project-1c7c380895ca

#next #flutter 

11 Coisas A Serem Lembradas Para O Seu Próximo Projeto Flutter
曾 俊

曾 俊

1660663800

下一个 Flutter 项目要记住的 11 件事

创建一个新的 Flutter 项目是一件幸事——新的代码库,没有遗留代码(还),null-safety,你最喜欢的包的最新版本等等。但同时,您应该在项目开始时做出关键决策,为未来奠定基础,例如工具、包、文件结构、状态管理解决方案、测试计划。否则,该项目最终将变成另一碗意大利面和肉丸。为了避免这种情况,我准备了一份我认为应该尽早决定的项目最重要元素的清单。因此,我希望它对您有所帮助-阅读愉快!

1.静态代码分析

我不会写乱码(源码

Linter是一种静态分析工具,可以识别和标记代码中的编程错误、警告和样式缺陷,以便您修复它们。在 Flutter 上下文中,这是最容易实现的事情之一,也是保持代码整洁最有帮助的事情之一。

您可以为代码设置大量不同的规则来遵循,但我建议使用已经遵循基于Dart 样式指南的最佳实践的预定义集之一:

无论您选择哪个包,您始终可以在analysis_options.yaml文件中添加或删除任何特定的静态分析规则。

2. 本地化(l10n)

本地化(来源

什么是本地化(简称l10n)?

本地化是对产品或服务的适应,以满足特定语言、文化或所需人群的“外观和感觉”的需求。—技术目标

必须构建一个用户感觉自然的应用程序,例如使用正确的翻译、日期和货币格式、文本方向。为此,本地化是使用的基本工具。即使您正在构建单个区域/语言的应用程序,我仍然建议您尽早实现本地化,从而将您的文本与 UI 代码分开。因此,它们可以在不影响代码的情况下被重用以及稍后进行调整。

Flutter 文档精美地解释了应用程序国际化的过程。如果默认方式看起来太复杂和/或您需要一些有用的扩展和辅助方法,那么有流行的第三方包,例如easy_localization,可以帮助您完成本地化过程。

3. 环境(有一些风味)

编程环境(来源

我敢打赌,当有人损坏数据或删除生产中的整个用户表时,您已经从您的环境中听到了至少一个案例(不是双关语)。相信我——这不好玩。因此,为您的项目创建不同的环境是一个很好的做法:

  • 开发(本地)环境——让你更轻松:在代码中进行实验,直接在数据库中更改数据,采用捷径并硬编码身份验证令牌或提供模拟数据。玩得开心并提供这些功能!
  • 中间环境(测试登台)——帮助您验证代码中的更改,使用“真实”数据测试功能(通常在此类环境中使用生产数据的快照)并在将应用程序发布到生产环境之前对其进行验证. 如果您的团队中有 QA 工程师,那么这里就是他们大放异彩的地方。
  • 生产环境——真实用户使用的环境,其中数据损坏是不可接受的(请始终进行备份)。

拥有这样的环境可以帮助您在这些更改落入用户手中之前安全地试验和验证功能。

现在,另一部分——味道。不不,我们不是在谈论甜、咸或酸的东西——这只是编程中用来描述应用程序不同构建变体的另一个术语。例如,您想让每个特定环境的图标和标题、API 端点或任何其他配置都不同。为此,您定义了在为特定环境构建应用程序时使用的不同“风格”。这里有一些关于如何为 Flutter 创建风味的资源。

4. 持续集成和持续交付(CI/CD)

持续集成 (CI) 和持续交付 (CD) 的阶段(来源

在引入不同的环境之后,自然而然的下一步就是自动化构建、测试和发布应用程序的过程。CI/CD本身就是一个相当复杂的话题,无论如何我都不是这个领域的专家,因此我建议搜索一些其他资源,了解如何自动化应用程序开发的不同阶段。

但是,有很多NoOps解决方案与 Flutter 兼容,因此您可以轻松地自动化您的开发过程:

这些解决方案中的任何一个都可以解决问题 - 只需选择适合您需求和预算的解决方案。

5.后端代码

关于后端的另一个模因(来源

您是否已经用任何异国情调或可能不是那么花哨的编程语言实现了后端?太好了,您可以跳过此步骤,但我仍然建议您检查一些云解决方案以供将来参考。

在简化版本中,应用程序的后端部分有两个选项:

  1. 使用您喜欢的任何编程语言和框架实现自定义后端解决方案,但稍后会处理所有DevOps内容以使您的代码和数据可从应用程序访问。
  2. 使用任何云解决方案来加快开发过程,并将大部分 DevOps 工作留给云提供商。

如果第二个选项对您有吸引力,有一些很棒的云平台可供选择,以支持 Flutter:

云平台为您的应用程序和许多其他功能提供身份验证、数据库、存储、API 选项。当您只需要验证想法并快速构建 MVP 而无需在成熟的后端解决方案上花费大量时间时,任何这些都是不错的选择。

6. 日志记录、崩溃数据和分析

糟糕,出了点问题(来源

日志记录被低估了——在这里,我说过了!一切都很酷,直到出现问题并且您需要有关该信息的信息。当我们讨论应该记录什么和不应该记录什么时,总是有一个灰色区域。但有一件事总是很清楚——您必须知道您的应用程序何时崩溃以及导致问题的原因。您收集的有关事件的数据越多,就越容易找到并解决问题。

SentryFirebase CrashlyticsDatadog 等服务可以帮助您记录最重要的数据、崩溃报告,甚至在您的应用程序或相关服务关闭时设置通知。

另一种类型的日志记录是为了分析目的而收集用户数据。当您构建一个全新的、可能是独一无二的产品时,了解用户的需求、他们的行为以及他们如何使用应用程序至关重要。为此,可以将各种分析工具集成到您的 Flutter 应用程序中,例如Firebase AnalyticsApp Center Analytics等等。

7. 应用品牌

材料主题(来源

任何应用程序或品牌的主要目标之一是被识别。使用正确的调色板、徽标、图标、设计元素、内容、字体,有时甚至布局可以让您的产品脱颖而出。那就是应用程序品牌化,一开始就准备好基础部分将在整个项目中为您节省大量时间。

如果您已经准备好您的 UI 原型或设计组件,那么现在是将它们转移到您的应用程序并定义主题的好时机——颜色、字体、形状等。为了更容易,好人Mike Rydstrom为这 — flex_color_scheme

8.项目结构和状态管理

Flutter 中的状态管理(源码

是的,有争议的。需要明确的是,没有“最好的状态管理解决方案”或“应用程序的最佳架构”之类​​的东西——如果有人这么说,请记住他们也可能在麦片粥之前将牛奶倒入碗中。这是最糟糕的部分——我无法教给你最好的方法。我只能提供几个选项或分享我的偏好。

下一个 Flutter 项目的几个文件结构选项:

  • 清洁架构——清晰的关注点分离,已经存在很长时间了。老实说,我不是这个的粉丝。我觉得这个概念中有太多抽象,可能会减慢开发过程。
  • 分层架构——依赖于将数据、业务和表示逻辑拆分为单独的层的想法。这样的文件结构对于中小型项目来说效果很好,但是我觉得随着项目的发展,这些层会变得越来越不堪重负。
  • 模块化架构(我在这里描述了这个概念)——将代码分成不同模块交互的每个功能的模块。这是我最喜欢的一个——它可以与 BLoC 状态管理解决方案(TEAM BLOC,YEAH!)顺利配合,非常适合大型项目。但是,它带来了一些挑战,比如通用逻辑放在哪里,不同的模块应该如何通信等等。

关于 Flutter 中的状态管理——我认为我们可以将整个会议专门用于这个主题,但之后还没有最终答案。只是为了增加我的两分钱,选择你觉得最舒服的一个。您可以在此处找到完整的选项列表。

9.代码生成

代码生成(来源

如果您想偷工减料并节省一些开发时间,您可以在项目中使用代码生成代码更少,交付更多

有一系列不同的工具可供使用,无论是使用本地化、资产、解析 JSON、生成模型类、实现服务定位器、路由还是使用不可变状态。唯一要做的就是调查可用的工具和包,然后选择最好的来满足您的项目需求。

为了快速启动 Flutter 项目,我建议您查看Very Good CLI。它将为您节省几个小时的配置时间(不幸的是,我已经很难学会了)。

另外,上个月我做了一个关于代码生成的演讲——它可能是你 Flutter 代码生成之旅的起点,所以看看吧!

10. 测试策略

应用程序测试(来源

用测试覆盖 100% 的代码是好是坏?当然,这很棒,但代价是什么?以这种方式思考,您可能会陷入注定要花更多时间编写测试而不是开发功能的坑中。为避免这种情况,您需要一个测试策略。

不要误解我的意思——用测试覆盖你的代码是一件很棒的事情,你的代码被覆盖得越多,你在实现新特性时就会感觉越安全。只是,在我看来,与编写测试所花费的时间相比,您应该找到测试仍然为您带来更多价值的平衡点。例如,这是我的测试策略:

  • 业务逻辑(服务、存储库、BLoC)应该在单元/集成测试中覆盖 85-100% ——这是任何应用程序中最重要的部分,所以我在那里的测试中看到了很多价值;
  • 小部件测试应涵盖所有可重用的 UI 组件。正确测试各个组件后,您可以开始测试各个屏幕,但不那么详细。
  • 端到端测试,涵盖主要的应用程序流程和与 UI 的交互。没有深层次的魔法——只是通过一些关键的工作流程。它们包含的屏幕越多越好。
  • 当整个 UI 准备好并实施时——黄金测试以确保 UI 不受以后更改的影响。

老实说,我仍在寻找测试中的中庸之道,但你会在一个又一个项目中做得更好,相信我。

11. 自述文件

编写自述文件(来源

你没听错——文档。README 文件是项目中最重要的文件,尤其是在团队工作时。

您是否刚刚介绍了需要代码生成的新解决方案?您是否刚刚添加了一个新的有用的 bash 脚本来自动化该过程?你是否实现了一个必须在项目中到处使用的全局记录器?我们无法读懂您的想法——请在 README 文件中提及!

没有太多的文档(至少我没有遇到过这种情况)只有缺乏关于项目和代码的信息。生成、测试和运行代码的所有命令、各种文件结构决策、图表、外部工具和服务、有关不同环境的信息(没有密钥)都应该放在这里并保存在一个地方。这是一项无聊的工作,但却是一项非常有益的工作!

 

唷,多么美妙的旅程……(来源

而已!感谢您花时间阅读这篇文章。

我错过了什么?在评论中提及!在构建新的 Flutter 应用程序时,你的清单是什么?

资料来源:https ://medium.com/flutter-community/11-things-to-remember-for-your-next-flutter-project-1c7c380895ca

#next #flutter 

下一个 Flutter 项目要记住的 11 件事
Diego  Elizondo

Diego Elizondo

1660662000

11 Cosas Que Debes Recordar Para Tu Próximo Proyecto De Flutter

Crear un nuevo proyecto de Flutter es una bendición: base de código nueva, sin código heredado (todavía), seguridad nula, versiones más recientes de sus paquetes favoritos, etc. Pero al mismo tiempo, debe tomar decisiones críticas al comienzo del proyecto que sentarían las bases para el futuro, como herramientas, paquetes, estructura de archivos, solución de administración de estado, plan de prueba. De lo contrario, el proyecto eventualmente se convertiría en otro plato de espaguetis y albóndigas. Para evitar esto, he preparado una lista de, en mi opinión, los elementos más importantes del proyecto que deben decidirse desde el principio. Espero que te ayude, por lo tanto, ¡feliz lectura!

1. Análisis de código estático

No escribiré código desordenado ( fuente )

Linter es una herramienta de análisis estático que identifica y marca errores de programación, advertencias, fallas de estilo en su código para que usted las corrija. En el contexto de Flutter, esa es una de las cosas más fáciles de implementar y una de las más útiles para mantener tu código limpio.

Hay toneladas de reglas diferentes que puede configurar para que siga su código, pero recomendaría usar uno de los conjuntos predefinidos que ya siguen las mejores prácticas basadas en la Guía de estilo de Dart :

Independientemente del paquete que elija, siempre puede agregar o eliminar cualquier regla de análisis estático específica en el archivo analysis_options.yaml .

2. Localización (l10n)

Localización ( fuente )

¿Qué es la localización ( l10n , en resumen)?

La localización es la adaptación de un producto o servicio para satisfacer las necesidades de un idioma en particular, una cultura o la “apariencia” deseada de la población. — TechTarget

Es esencial construir una aplicación que se sienta natural para los usuarios, por ejemplo, usando las traducciones correctas, los formatos de fecha y moneda, la dirección del texto. Para eso, la localización es una herramienta fundamental a utilizar. Aunque esté creando una aplicación de una sola región/idioma, aún le recomendaría que implemente la localización desde el principio, separando así sus textos del código de la interfaz de usuario. En consecuencia, podrían reutilizarse y ajustarse más adelante sin afectar el código.

La documentación de Flutter explica de forma exquisita el proceso de internacionalización de tu aplicación. Si la forma predeterminada parece demasiado compleja y/o necesita algunas extensiones útiles y métodos auxiliares, existen paquetes populares de terceros, como easy_localization , que podrían ayudarlo con el proceso de localización.

3. Ambientes (con algunos sabores)

Entornos de programación ( fuente )

Apuesto a que ya ha escuchado al menos un caso de su entorno (sin juego de palabras) cuando alguien corrompió los datos o eliminó toda la tabla de usuarios en producción. Confía en mí, esto no es divertido. Por lo tanto, es una buena práctica crear diferentes entornos para su proyecto:

  • Entorno de desarrollo (local): se usa para volverse loco: hacer experimentos en el código, cambiar datos directamente en la base de datos, tomar accesos directos y codificar el token de autenticación o proporcionar datos simulados. ¡Diviértete y entrega esas características!
  • Un entorno intermedio ( prueba o puesta en escena ): lo ayuda a validar los cambios en el código, probar las funciones con los datos "reales" (por lo general, en dichos entornos se usa una instantánea de los datos de producción) y verificar la aplicación antes de lanzarla a producción. . Si tiene ingenieros de control de calidad en su equipo, este es el lugar para que brillen.
  • Entorno de producción : el que utilizan los usuarios reales, donde la corrupción de datos no es aceptable (siempre haga copias de seguridad, por favor).

Tener dichos entornos lo ayuda a experimentar y verificar características de manera segura antes de que esos cambios lleguen a manos de los usuarios.

Ahora, otra parte: sabores . No, no, no estamos hablando de algo dulce, salado o agrio; ese es solo otro término que se usa en programación para describir diferentes variantes de compilación para su aplicación. Por ejemplo, desea que el icono y el título, el punto final de la API o cualquier otra configuración sean diferentes para cada entorno específico. Para eso, define un "sabor" diferente que se usa cuando la aplicación se está construyendo para un entorno específico. Aquí hay algunos recursos sobre cómo crear sabores para Flutter .

4. Integración Continua y Entrega Continua (CI/CD)

Etapas de Integración Continua (CI) y Entrega Continua (CD) ( fuente )

Después de introducir diferentes entornos, el siguiente paso natural es automatizar el proceso de creación, prueba y lanzamiento de su aplicación. CI/CD es un tema bastante complejo en sí mismo y no soy un experto en este campo de ninguna manera, por lo tanto, recomendaría buscar otros recursos sobre cómo automatizar las diferentes etapas del desarrollo de aplicaciones.

Sin embargo, hay muchas soluciones NoOps que son compatibles con Flutter para que pueda automatizar su proceso de desarrollo con facilidad:

Cualquiera de esas soluciones haría el truco: simplemente, seleccione la que se ajuste a sus necesidades y presupuesto.

5. Código de fondo

Una vez más meme sobre backend ( fuente )

¿Ya tienes tu backend implementado en algún lenguaje de programación exótico o quizás no tan sofisticado? Genial, puede omitir este paso, pero aun así recomendaría revisar algunas soluciones en la nube para futuras referencias.

En la versión simplificada, hay dos opciones para la parte de backend de su aplicación:

  1. Implementar una solución de back-end personalizada utilizando cualquier lenguaje de programación y marco que desee, pero luego ocuparse de todas las cosas de DevOps para que su código y datos sean accesibles desde la aplicación.
  2. Usar cualquier solución en la nube para acelerar el proceso de desarrollo y dejar la mayor parte del trabajo de DevOps para el proveedor de la nube.

En caso de que la segunda opción te parezca atractiva, hay algunas excelentes plataformas en la nube para elegir compatibles con Flutter:

Las plataformas en la nube brindan autenticación, base de datos, almacenamiento, opciones de API para su aplicación y muchas otras características. Cualquiera de estos es una excelente opción cuando solo necesita validar la idea y construir el MVP rápidamente sin perder mucho tiempo en la solución de back-end completa.

6. Registro, datos de fallas y análisis

Vaya, algo salió mal ( fuente )

El registro está subestimado, ¡aquí lo dije! Todo va bien hasta que algo sale mal y necesitas información al respecto. Siempre hay un área gris cuando discutimos qué se debe registrar y qué no. Pero una cosa siempre está clara: debe saber cuándo falla su aplicación y qué causa el problema. Cuantos más datos recopile sobre el incidente, más fácil será encontrar y solucionar el problema.

Los servicios como Sentry , Firebase Crashlytics , Datadog podrían ayudarlo a registrar los datos más importantes, informes de fallas o incluso configurar notificaciones cuando su aplicación o servicios relacionados están inactivos.

Otro tipo de registro es la recopilación de datos de usuario con fines de análisis. Cuando crea un producto nuevo, tal vez único, es fundamental comprender las necesidades de los usuarios, su comportamiento y cómo utilizan la aplicación. Para esto, se podrían integrar varias herramientas de análisis en su aplicación Flutter, como Firebase Analytics , App Center Analytics y muchas más.

7. Aplicación de marca

Tematización de materiales ( fuente )

Uno de los principales objetivos de cualquier aplicación o marca es ser reconocible. El uso de la paleta de colores, el logotipo, los íconos, los elementos de diseño, el contenido, la fuente y, a veces, incluso el diseño, hacen que su producto se destaque de los demás. Eso es branding de aplicaciones , y preparar las partes fundamentales al principio te ahorrará mucho tiempo durante todo el proyecto.

Si ya tiene listo su prototipo de interfaz de usuario o los componentes de diseño, ahora es un buen momento para transferirlos a su aplicación y definir temas: colores, fuentes, formas, etc. Para hacerlo más fácil, un buen tipo, Mike Rydstrom , creó un paquete excepcional para esto — flex_color_scheme .

8. Estructura del proyecto y gestión estatal

Gestión de estados en Flutter ( fuente )

Sí, la polémica. Para que quede claro, no existe tal cosa como "la mejor solución de administración de estado" o "la mejor arquitectura de la aplicación". Si alguien dice lo contrario, recuerde que probablemente también vierta leche en el tazón antes que el cereal. Y esa es la peor parte: no puedo enseñarte la mejor manera. Solo puedo proporcionar varias opciones o compartir mis preferencias.

Varias opciones de estructura de archivos para el próximo proyecto de Flutter:

  • Arquitectura limpia : clara separación de preocupaciones, existe desde hace mucho tiempo. Honestamente, no soy fanático de esto. Siento que hay demasiada abstracción en este concepto que podría retrasar el proceso de desarrollo.
  • Arquitectura en capas : se basa en la idea de dividir la lógica de datos, negocios y presentación en capas separadas. Esta estructura de archivos funciona bien para proyectos pequeños y medianos, pero creo que estas capas se vuelven cada vez más abrumadoras a medida que crece el proyecto.
  • Arquitectura modular (he descrito este concepto aquí ): dividir el código en módulos por característica donde interactúan diferentes módulos. Este es mi favorito: funciona sin problemas con la solución de gestión de estado BLoC (TEAM BLOC, ¡SÍ!), Se adapta bien a grandes proyectos. Sin embargo, presenta algunos desafíos, como dónde poner la lógica común, cómo deben comunicarse los diferentes módulos, etc.

Acerca de la administración estatal en Flutter: creo que estamos en el punto en el que podríamos dedicar toda la conferencia a este tema y, sin embargo, no tenemos una respuesta final después. Solo para agregar mis dos centavos, elija el que se sienta más cómodo. Puede encontrar una lista completa de opciones aquí .

9. Generación de código

Generación de código ( fuente )

Si desea reducir algunos gastos y ahorrar algo de tiempo de desarrollo, puede utilizar la generación de código en su proyecto. ¡ Codifique menos, entregue más !

Hay una variedad de herramientas diferentes para usar, ya sea trabajando con localizaciones, activos, analizando JSON, generando clases de modelos, implementando el localizador de servicios, enrutamiento o trabajando con estados inmutables. Lo único que debe hacer es investigar las herramientas y paquetes disponibles y elegir los mejores para cubrir las necesidades de su proyecto.

Para un inicio rápido del proyecto Flutter, recomendaría consultar Very Good CLI . Le ahorraría varias horas de configuración (desafortunadamente, lo he aprendido de la manera más difícil).

Además, el mes pasado di una charla sobre la generación de código : podría ser un punto de partida para tu viaje de generación de código Flutter, ¡así que échale un vistazo!

10. Estrategia de prueba

Pruebas de aplicaciones ( fuente )

¿Es bueno o malo cubrir el 100% de tu código con pruebas? Claro, es increíble, pero ¿a qué costo? Pensando de esta manera, podría caer en el pozo condenado donde pasa más tiempo escribiendo pruebas que desarrollando características. Para evitar esto, necesita una estrategia de prueba.

No me malinterpreten: cubrir su código con pruebas es una gran cosa y mientras más lugares oscuros de su código estén cubiertos, más seguro se sentirá al implementar nuevas funciones. Simplemente, en mi opinión, debe encontrar el equilibrio en el que las pruebas aún le brinden más valor en comparación con el tiempo dedicado a escribirlas. Por ejemplo, esta es mi estrategia de prueba:

  • La lógica empresarial (servicios, repositorios, BLoC) debe cubrirse en un 85-100 % en las pruebas unitarias/de integración ; esta es la parte más importante de cualquier aplicación, por lo que veo mucho valor en las pruebas allí;
  • Las pruebas de widgets deben cubrir todos los componentes de la interfaz de usuario reutilizables. Cuando los componentes individuales se prueban correctamente, puede comenzar a probar pantallas individuales pero con menos detalle.
  • Pruebas de extremo a extremo , que cubren los principales flujos de aplicaciones e interacciones con la interfaz de usuario. Sin magia de nivel profundo, solo pasando por algunos flujos de trabajo cruciales. Cuantas más pantallas incluyan, mejor.
  • Cuando toda la interfaz de usuario esté lista e implementada, pruebas doradas para garantizar que la interfaz de usuario no se vea afectada por cambios posteriores.

Honestamente, todavía estoy buscando ese medio dorado en las pruebas, pero se mejora proyecto tras proyecto, confía en mí.

11. Archivo LÉAME

Haz un README ( fuente )

Me has oído bien: documentación. El archivo README es el documento más importante del proyecto, especialmente cuando se trabaja en equipo.

¿Acaba de presentar una nueva solución que requiere la generación de código? ¿Acaba de agregar un nuevo script bash útil para automatizar el proceso? ¿Ha implementado un registrador global que DEBE usarse en todas partes del proyecto? No podemos leer su mente, ¡mencione eso en el archivo README!

No existe demasiada documentación (al menos yo no he estado en esa situación), solo la falta de información sobre el proyecto y el código. Todos los comandos para generar, probar y ejecutar el código, varias decisiones de estructura de archivos, diagramas, herramientas y servicios externos, información sobre diferentes entornos (SIN CLAVES SECRETAS) deben colocarse aquí y mantenerse en un solo lugar. ¡Este es un trabajo aburrido pero muy gratificante!

 

Uf, qué paseo... ( fuente )

¡Eso es todo! Gracias por tu tiempo leyendo este artículo.

¿Me he perdido algo? Menciona eso en los comentarios! ¿Cuál es su lista de verificación al crear una nueva aplicación Flutter?

Fuente: https://medium.com/flutter-community/11-things-to-remember-for-your-next-flutter-project-1c7c380895ca

#next #flutter 

11 Cosas Que Debes Recordar Para Tu Próximo Proyecto De Flutter

11 Choses à Retenir Pour Votre Prochain Projet Flutter

La création d'un nouveau projet Flutter est une bénédiction - une nouvelle base de code, pas (encore) de code hérité, une sécurité nulle, les versions les plus récentes de vos packages préférés, etc. Mais en même temps, vous devez prendre des décisions critiques au début du projet qui jetteront les bases de l'avenir, telles que l'outillage, les packages, la structure des fichiers, la solution de gestion d'état, le plan de test. Sinon, le projet finirait par se transformer en un autre bol de spaghettis et de boulettes de viande. Pour éviter cela, j'ai préparé une liste de, à mon avis, les éléments les plus importants du projet qui devraient être décidés dès le début. J'espère que cela vous aidera, donc - bonne lecture!

1. Analyse de code statique

Je n'écrirai pas de code compliqué ( source )

Linter est un outil d'analyse statique qui identifie et signale les erreurs de programmation, les avertissements et les défauts de style dans votre code pour que vous puissiez les corriger. Dans le contexte Flutter, c'est l'une des choses les plus faciles à implémenter et l'une des plus utiles pour garder votre code propre.

Il existe des tonnes de règles différentes que vous pouvez définir pour votre code, mais je vous recommande d'utiliser l'un des ensembles prédéfinis qui suit déjà les meilleures pratiques basées sur le Dart Style Guide :

Quel que soit le package que vous choisissez, vous pouvez toujours ajouter ou supprimer une règle d'analyse statique spécifique dans le fichier analysis_options.yaml .

2. Localisation (l10n)

Localisation ( source )

Qu'est-ce que la localisation ( l10n , en bref) ?

La localisation est l'adaptation d'un produit ou d'un service pour répondre aux besoins d'une langue, d'une culture ou de l'apparence d'une population particulière. — TechTarget

Il est essentiel de créer une application qui semble naturelle aux utilisateurs, par exemple en utilisant les bonnes traductions, les formats de date et de devise, la direction du texte. Pour cela, la localisation est un outil fondamental à utiliser. Même si vous construisez une seule application de région/langue, je vous recommande toujours de mettre en œuvre la localisation dès le début, séparant ainsi vos textes du code de l'interface utilisateur. Par conséquent, ils pourraient être réutilisés et ajustés ultérieurement sans affecter le code.

La documentation Flutter explique de manière exquise le processus d'internationalisation de votre application. Si la méthode par défaut semble trop complexe et/ou si vous avez besoin d'extensions et de méthodes d'assistance utiles, il existe des packages tiers populaires, tels que easy_localization , qui pourraient vous aider dans le processus de localisation.

3. Environnements (avec quelques saveurs)

Environnements de programmation ( source )

Je parie que vous avez déjà entendu au moins un cas de votre environnement (sans jeu de mots) lorsque quelqu'un a corrompu des données ou supprimé toute la table des utilisateurs en production. Croyez-moi - ce n'est pas amusant. Par conséquent, il est recommandé de créer différents environnements pour votre projet :

  • Environnement de développement (local) - utilisé pour vous rendre fou : faites des expériences dans le code, modifiez les données directement dans la base de données, prenez des raccourcis et codez en dur le jeton d'authentification ou fournissez des données simulées. Amusez-vous et offrez ces fonctionnalités !
  • Un environnement intermédiaire ( test ou staging ) — vous aide à valider les changements dans le code, à tester les fonctionnalités avec les données « réelles » (généralement, un instantané des données de production est utilisé dans de tels environnements) et à vérifier l'application avant de la mettre en production. . Si vous avez des ingénieurs QA dans votre équipe, c'est l'endroit idéal pour eux.
  • Environnement de production - celui qui est utilisé par de vrais utilisateurs, où la corruption des données n'est pas acceptable (faites toujours des sauvegardes, s'il vous plaît).

Avoir de tels environnements vous aide à expérimenter et à vérifier en toute sécurité les fonctionnalités avant que ces modifications ne soient entre les mains des utilisateurs.

Maintenant, une autre partie — les saveurs . Non non, nous ne parlons pas de quelque chose de sucré, salé ou aigre - ce n'est qu'une fois un autre terme utilisé en programmation pour décrire différentes variantes de construction pour votre application. Par exemple, vous souhaitez que l'icône et le titre, le point de terminaison de l'API ou toute autre configuration soient différents pour chaque environnement spécifique. Pour cela, vous définissez une "saveur" différente qui est utilisée lorsque l'application est construite pour un environnement spécifique. Voici quelques ressources sur la façon de créer des saveurs pour Flutter .

4. Intégration continue et livraison continue (CI/CD)

Étapes de l'intégration continue (CI) et de la livraison continue (CD) ( source )

Après avoir introduit différents environnements, la prochaine étape naturelle consiste à automatiser le processus de création, de test et de publication de votre application. CI / CD est un sujet assez complexe en soi et je ne suis en aucun cas un expert dans ce domaine. Je recommanderais donc de rechercher d'autres ressources sur la manière d'automatiser les différentes étapes du développement d'applications.

Cependant, de nombreuses solutions NoOps sont compatibles avec Flutter afin que vous puissiez automatiser facilement votre processus de développement :

N'importe laquelle de ces solutions ferait l'affaire - sélectionnez simplement celle qui correspond à vos besoins et à votre budget.

5. Code principal

Une fois un autre meme sur le backend ( source )

Avez-vous déjà implémenté votre backend dans un langage de programmation exotique ou peut-être moins sophistiqué ? Génial, vous pouvez ignorer cette étape, mais je vous recommande tout de même de vérifier certaines solutions cloud pour référence future.

Dans la version simplifiée, il existe deux options pour la partie backend de votre application :

  1. Implémenter une solution backend personnalisée en utilisant n'importe quel langage de programmation et framework que vous aimez, mais plus tard en prenant soin de tous les trucs DevOps pour rendre votre code et vos données accessibles depuis l'application.
  2. Utiliser n'importe quelle solution cloud pour accélérer le processus de développement et laisser la majeure partie du travail DevOps au fournisseur de cloud.

Si la deuxième option vous semble attrayante, vous pouvez choisir parmi d'excellentes plates-formes cloud prenant en charge Flutter :

Les plates-formes cloud fournissent l'authentification, la base de données, le stockage, les options d'API pour votre application et de nombreuses autres fonctionnalités. N'importe lequel d'entre eux est un excellent choix lorsque vous avez juste besoin de valider l'idée et de créer rapidement le MVP sans passer beaucoup de temps sur la solution backend complète.

6. Journalisation, données de plantage et analyses

Oups, quelque chose s'est mal passé ( source )

La journalisation est sous-estimée - ici, je l'ai dit! Tout va bien jusqu'à ce que quelque chose tourne mal et vous avez besoin d'informations à ce sujet. Il y a toujours une zone grise lorsque nous discutons de ce qui doit être enregistré et de ce qui ne l'est pas. Mais une chose est toujours claire : vous devez savoir quand votre application plante et quelle est la cause du problème. Plus vous collectez de données sur l'incident, plus il devient facile de trouver et de résoudre le problème.

Des services comme Sentry , Firebase Crashlytics , Datadog pourraient vous aider à consigner les données les plus importantes, les rapports de plantage ou même configurer des notifications lorsque votre application ou les services associés sont en panne.

Un autre type de journalisation consiste à collecter des données utilisateur à des fins d'analyse. Lorsque vous créez un nouveau produit, peut-être unique en son genre, il est essentiel de comprendre les besoins de vos utilisateurs, leur comportement et la manière dont ils utilisent l'application. Pour cela, divers outils d'analyse pourraient être intégrés à votre application Flutter, tels que Firebase Analytics , App Center Analytics et bien d'autres.

7. Image de marque de l'application

Thématisation matérielle ( source )

L'un des principaux objectifs de toute application ou marque est d'être reconnaissable. En utilisant la bonne palette de couleurs, le logo, les icônes, les éléments de conception, le contenu, la police, parfois même la mise en page, votre produit se démarque des autres. C'est l' image de marque de l'application , et préparer les éléments fondamentaux au début vous fera gagner beaucoup de temps tout au long du projet.

Si vous avez déjà votre prototype d'interface utilisateur ou vos composants de conception prêts, c'est maintenant le bon moment pour les transférer dans votre application et définir les thèmes - couleurs, polices, formes, etc. Pour vous faciliter la tâche, un bon gars Mike Rydstrom a créé un package exceptionnel pour ceci — flex_color_scheme .

8. Structure du projet et gestion de l'état

Gestion des états dans Flutter ( source )

Oui, la controversée. Juste pour être clair, il n'y a pas de "meilleure solution de gestion d'état" ou "la meilleure architecture de l'application" - si quelqu'un dit le contraire, rappelez-vous qu'il verse probablement du lait dans le bol avant les céréales aussi. Et c'est le pire — je ne peux pas vous apprendre la meilleure façon. Je ne peux proposer que plusieurs options ou partager mes préférences.

Plusieurs options de structure de fichiers pour le prochain projet Flutter :

  • Architecture propre - séparation claire des préoccupations, est là depuis longtemps. Honnêtement, je ne suis pas fan de ça. Je pense qu'il y a trop d'abstraction dans ce concept qui pourrait ralentir le processus de développement.
  • Architecture en couches - repose sur l'idée de diviser les données, la logique commerciale et de présentation en couches distinctes. Une telle structure de fichiers fonctionne bien pour les projets de petite à moyenne taille, mais j'ai l'impression que ces couches deviennent de plus en plus écrasantes lorsque le projet grandit.
  • Architecture modulaire (j'ai décrit ce concept ici ) - fractionnement du code en modules par fonctionnalité où différents modules interagissent. Celui-ci est mon préféré - il fonctionne sans problème avec la solution de gestion d'état BLoC (TEAM BLOC, YEAH !), s'adapte bien aux grands projets. Cependant, cela pose certains défis, comme où mettre la logique commune, comment les différents modules doivent communiquer, etc.

À propos de la gestion de l'état dans Flutter - je pense que nous sommes au point où nous pourrions consacrer toute la conférence à ce sujet et pourtant n'avoir aucune réponse définitive par la suite. Juste pour ajouter mes deux cents, choisissez celui avec lequel vous vous sentez le plus à l'aise. Vous pouvez trouver une liste complète des options ici .

9. Génération de code

Génération de code ( source )

Si vous voulez couper les coins ronds et gagner du temps de développement, vous pouvez utiliser la génération de code dans votre projet. Codez moins, livrez plus !

Il existe une gamme d'outils différents à utiliser, qu'il s'agisse de travailler avec des localisations, des actifs, d'analyser JSON, de générer des classes de modèles, d'implémenter un localisateur de service, de router ou de travailler avec des états immuables. La seule chose à faire est d'étudier les outils et packages disponibles et de choisir les meilleurs pour couvrir les besoins de votre projet.

Pour un lancement rapide du projet Flutter, je vous recommande de consulter le Very Good CLI . Cela vous ferait gagner plusieurs heures de configuration (malheureusement, je l'ai appris à mes dépens).

De plus, le mois dernier, j'ai donné une conférence sur la génération de code - cela pourrait être un point de départ pour votre parcours de génération de code Flutter, alors jetez un coup d'œil !

10. Stratégie de test

Test d'application ( source )

Est-ce bien ou mal de couvrir 100% de votre code avec des tests ? Certes, c'est génial, mais à quel prix ? En pensant de cette façon, vous pourriez tomber dans le gouffre voué à l'échec où vous passerez plus de temps à écrire des tests qu'à développer des fonctionnalités. Pour éviter cela, vous avez besoin d'une stratégie de test.

Ne vous méprenez pas - couvrir votre code avec des tests est une bonne chose et plus les endroits sombres de votre code sont couverts, plus vous pouvez vous sentir en sécurité lors de la mise en œuvre de nouvelles fonctionnalités. Juste, à mon avis, vous devriez trouver l'équilibre où les tests vous apportent encore plus de valeur par rapport au temps passé à les écrire. Par exemple, voici ma stratégie de test :

  • La logique métier (services, référentiels, BLoC) doit être couverte à 85-100 % dans les tests unitaires/d'intégration - c'est la partie la plus importante de toute application, donc je vois beaucoup de valeur dans les tests ;
  • Les tests de widget doivent couvrir tous les composants réutilisables de l'interface utilisateur. Lorsque les composants individuels sont testés correctement, vous pouvez commencer à tester des écrans individuels, mais avec moins de détails.
  • Tests de bout en bout , couvrant les principaux flux applicatifs et les interactions avec l'UI. Pas de magie de niveau profond - juste en passant par certains flux de travail cruciaux. Plus ils incluent d'écrans, mieux c'est.
  • Lorsque toute l'interface utilisateur est prête et implémentée - des tests en or pour s'assurer que l'interface utilisateur n'est pas affectée par des modifications ultérieures.

Honnêtement, je suis toujours à la recherche de ce juste milieu dans les tests, mais vous vous améliorez projet après projet, croyez-moi.

11. Fichier LISEZMOI

Faire un README ( source )

Vous m'avez bien entendu - documentation. Le fichier README est le document le plus important du projet, surtout lorsque l'on travaille en équipe.

Vous venez d'introduire une nouvelle solution nécessitant une génération de code ? Vous venez d'ajouter un nouveau script bash utile pour automatiser le processus ? Avez-vous implémenté un logger global qui DOIT être utilisé partout dans le projet ? Nous ne pouvons pas lire dans vos pensées — mentionnez-le dans le fichier README !

Il n'y a pas trop de documentation (du moins je n'ai pas été dans une telle situation) seulement le manque d'informations sur le projet et le code. Toutes les commandes pour générer, tester et exécuter le code, les diverses décisions de structure de fichiers, les diagrammes, les outils et services externes, les informations sur les différents environnements (SANS CLÉS SECRÈTES) doivent être placées ici et conservées à un seul endroit. C'est un travail ennuyeux mais très gratifiant !

 

Ouf, quelle balade… ( source )

C'est ça! Merci d'avoir pris le temps de lire cet article.

Ai-je oublié quelque chose? Mentionnez-le dans les commentaires ! Quelle est votre liste de contrôle lors de la création d'une nouvelle application Flutter ?

Source : https://medium.com/flutter-community/11-things-to-remember-for-your-next-flutter-project-1c7c380895ca

#next #flutter 

11 Choses à Retenir Pour Votre Prochain Projet Flutter
坂本  健一

坂本 健一

1660661160

次の Flutter プロジェクトで覚えておくべき 11 のこと

新しい Flutter プロジェクトを作成することは、新しいコードベース、(まだ) レガシー コードがない、null 安全性、お気に入りのパッケージの最新バージョンなど、ありがたいことです。しかし同時に、プロジェクトの開始時に、ツール、パッケージ、ファイル構造、状態管理ソリューション、テスト計画など、将来の基盤となる重要な決定を行う必要があります。そうしないと、プロジェクトは最終的に、スパゲッティとミートボールの単なる別のボウルになってしまいます。これを避けるために、私の意見では、早い段階で決定すべきプロジェクトの最も重要な要素のリストを用意しました。したがって、それがあなたの助けになることを願っています—幸せな読書!

1.静的コード分析

面倒なコードは書きません ( source )

Linterは、コード内のプログラミング エラー、警告、スタイルの欠陥を特定してフラグを立て、修正できるようにする静的分析ツールです。Flutter のコンテキストでは、これは実装するのが最も簡単なことの 1 つであり、コードをクリーンに保つのに最も役立つものの 1 つです。

コードが従うように設定できるさまざまなルールがありますが、 Dart スタイル ガイドに基づいたベスト プラクティスに既に従っている定義済みのセットのいずれかを使用することをお勧めします。

どのパッケージを選択しても、 analysis_options.yamlファイルで特定の静的分析ルールをいつでも追加または削除できます。

2. ローカリゼーション (l10n)

ローカリゼーション (ソース)

ローカリゼーション(略してl10n )とは何ですか?

ローカリゼーションとは、特定の言語、文化、または希望する母集団の「ルック アンド フィール」のニーズを満たすために、製品またはサービスを適応させることです。— TechTarget

適切な翻訳、日付と通貨の形式、テキストの方向など、ユーザーが自然に感じるアプリケーションを構築することが不可欠です。そのために、ローカリゼーションは使用する基本的なツールです。単一の地域/言語アプリケーションを構築している場合でも、早い段階でローカリゼーションを実装して、UI コードからテキストを分離することをお勧めします。したがって、コードに影響を与えることなく、再利用したり、後で調整したりできます。

Flutter のドキュメントは、アプリケーションの国際化のプロセスを精巧に説明しています。デフォルトの方法が複雑すぎると思われる場合、および/または便利な拡張機能やヘルパー メソッドが必要な場合は、easy_localizationなどの一般的なサードパーティ パッケージがローカライズ プロセスに役立ちます。

3.環境(いくつかのフレーバーを含む)

プログラミング環境 ( source )

誰かがデータを破損したり、本番環境でユーザーのテーブル全体を削除したりした場合、あなたの環境から少なくとも 1 つのケース (しゃれは意図されていません) を聞いたことがあると思います。私を信じてください—これは面白くありません。したがって、プロジェクト用にさまざまな環境を作成することをお勧めします。

  • 開発(ローカル) 環境 — コードで実験を行ったり、データベースで直接データを変更したり、ショートカットを使用して認証トークンをハードコーディングしたり、模擬データを提供したりするために使用されます。楽しんで、それらの機能を提供してください!
  • 中間環境 (テストまたはステージング) — コードの変更を検証し、「実際の」データを使用して機能をテストし (通常、そのような環境では本番データのスナップショットが使用されます)、本番環境にリリースする前にアプリケーションを検証するのに役立ちます。 . チームに QA エンジニアがいる場合、ここが彼らの活躍の場です。
  • 実稼働環境 — 実際のユーザーが使用する環境で、データの破損が許容されない (常にバックアップを行ってください)。

このような環境を用意することで、変更がユーザーの手に渡る前に、機能を安全に実験および検証することができます。

さて、別の部分 —フレーバー. いいえ、甘いもの、塩辛いもの、酸っぱいものについて話しているわけではありません。これは、アプリケーションのさまざまなビルド バリアントを説明するためにプログラミングで使用される別の用語です。たとえば、アイコンとタイトル、API エンドポイント、またはその他の構成を特定の環境ごとに異なるものにしたい場合などです。そのために、アプリケーションが特定の環境用に構築されているときに使用される別の「フレーバー」を定義します。Flutter のフレーバーを作成する方法に関するリソースを次に示します。

4. 継続的インテグレーションと継続的デリバリー (CI/CD)

継続的インテグレーション (CI) と継続的デリバリー (CD) の段階 ( source )

さまざまな環境を導入した後、自然な次のステップは、アプリケーションの構築、テスト、およびリリースのプロセスを自動化することです。CI/CDはそれ自体が非常に複雑なトピックであり、私は決してこの分野の専門家ではありません。そのため、アプリケーション開発のさまざまな段階を自動化する方法について、他のリソースを検索することをお勧めします。

ただし、Flutter と互換性のある多くのNoOpsソリューションがあるため、開発プロセスを簡単に自動化できます。

これらのソリューションはどれでもうまくいきます。単に、ニーズと予算に合ったものを選択してください.

5. バックエンド コード

バックエンドに関するもう 1 つのミーム ( source )

バックエンドをエキゾチックなプログラミング言語やあまり派手ではないプログラミング言語で実装していますか? この手順は省略できますが、今後の参考のためにいくつかのクラウド ソリューションを確認することをお勧めします。

簡易バージョンでは、アプリケーションのバックエンド部分に 2 つのオプションがあります。

  1. 任意のプログラミング言語とフレームワークを使用してカスタム バックエンド ソリューションを実装しますが、後ですべてのDevOpsを処理して、アプリケーションからコードとデータにアクセスできるようにします。
  2. 任意のクラウド ソリューションを使用して開発プロセスをスピードアップし、DevOps 作業のほとんどをクラウド プロバイダーに任せます。

2 番目のオプションが魅力的であると思われる場合は、Flutter をサポートする優れたクラウド プラットフォームがいくつかあります。

クラウド プラットフォームは、アプリケーションの認証、データベース、ストレージ、API オプション、およびその他の多くの機能を提供します。本格的なバックエンド ソリューションに多くの時間を費やすことなく、アイデアを検証して MVP を迅速に構築する必要がある場合は、これらのいずれもが優れた選択肢です。

6. ロギング、クラッシュ データ、分析

おっと、何か問題が発生しました ( source )

ロギングは過小評価されています — ここで言いました! 何か問題が発生し、それに関する情報が必要になるまでは、すべて問題ありません。何をログに記録し、何をログに記録しないかを議論するとき、常に灰色の領域があります。ただし、常に明確なことが 1 つあります。それは、アプリケーションがいつクラッシュし、何が問題を引き起こしているのかを知っておく必要があるということです。インシデントに関して収集するデータが多ければ多いほど、問題を見つけて修正することが容易になります。

SentryFirebase CrashlyticsDatadogなどのサービスは、最も重要なデータのログ記録、クラッシュ レポート、さらにはアプリケーションや関連サービスがダウンしたときの通知の設定に役立ちます。

もう 1 つのタイプのロギングは、分析目的でユーザー データを収集することです。斬新な、おそらく唯一無二の製品を構築する場合、ユーザーのニーズ、ユーザーの行動、およびユーザーがアプリケーションをどのように使用しているかを理解することが重要です。このために、 Firebase AnalyticsApp Center Analyticsなど、さまざまな分析ツールを Flutter アプリケーションに統合できます。

7. アプリケーションのブランディング

マテリアル テーマ (ソース)

アプリケーションやブランドの主な目標の 1 つは、認識できるようにすることです。適切なカラー パレット、ロゴ、アイコン、デザイン要素、コンテンツ、フォント、場合によってはレイアウトを使用することで、製品が他の製品より際立つようになります。それがアプリケーションのブランディングであり、最初に基本的な部分を準備すると、プロジェクト全体で多くの時間を節約できます。

すでに UI プロトタイプまたはデザイン コンポーネントの準備ができている場合は、それらをアプリケーションに転送し、テーマ (色、フォント、形状など) を定義する良い機会です。これ — flex_color_scheme

8. プロジェクト構造と状態管理

Flutter での状態管理 ( source )

はい、物議を醸すもの。念のために言っておきますが、「最良の状態管理ソリューション」や「アプリケーションの最良のアーキテクチャ」などというものはありません。別の言い方をすれば、シリアルの前に牛乳をボウルに注ぐことも忘れないでください。そして、それが最悪の部分です — 私はあなたに最善の方法を教えることはできません. いくつかのオプションを提供するか、好みを共有することしかできません.

次の Flutter プロジェクトのいくつかのファイル構造オプション:

  • クリーンなアーキテクチャ— 懸念事項の明確な分離は、長い間存在しています。正直なところ、私はこれのファンではありません。この概念には抽象化が多すぎるため、開発プロセスが遅くなる可能性があると感じています。
  • レイヤード アーキテクチャ— データ、ビジネス、およびプレゼンテーション ロジックを別々のレイヤーに分割するという考え方に依存しています。このようなファイル構造は、小規模から中規模のプロジェクトでは問題なく機能しますが、プロジェクトが大きくなると、これらのレイヤーがますます圧倒されるように感じます。
  • モジュラー アーキテクチャ (この概念についてはここで説明しました) — コードを機能ごとにモジュールに分割し、異なるモジュールが相互作用します。これは私のお気に入りです。BLoC 状態管理ソリューション (TEAM BLOC、YEAH!) とスムーズに連携し、大きなプロジェクトに適しています。ただし、共通のロジックをどこに配置するか、異なるモジュールがどのように通信する必要があるかなど、いくつかの課題が生じます。

Flutter での状態管理について— カンファレンス全体をこのトピックに専念できるところまで来ていると思いますが、その後の最終的な回答はありません。私の2セントを追加するために、あなたが最も快適に感じるものを選択してください. ここでオプションの包括的なリストを見つけることができます。

9. コード生成

コード生成 (ソース)

手抜きをして開発時間を節約したい場合は、プロジェクトでコード生成を使用できます。コードを少なくして、より多くを提供しましょう!

ローカリゼーション、アセットの操作、JSON の解析、モデル クラスの生成、サービス ロケーターの実装、ルーティング、不変状態の操作など、さまざまなツールを使用できます。唯一できることは、利用可能なツールとパッケージを調査し、プロジェクトのニーズを満たすのに最適なものを選択することです。

Flutter プロジェクトのクイック キックオフについては、Very Good CLIを確認することをお勧めします。これにより、設定にかかる時間を数時間節約できます (残念ながら、私は苦労して習得しました)。

また、先月はコード生成についての講演を行いました。Flutter コード生成の旅の出発点になる可能性があるので、ぜひチェックしてください。

10. テスト戦略

アプリケーションのテスト (ソース)

コードの 100% をテストでカバーすることは良いことですか、それとも悪いことですか? 確かに、それは素晴らしいですが、どのくらいの費用がかかりますか? このように考えると、機能の開発よりもテストの作成に多くの時間を費やす運命に陥る可能性があります。これを回避するには、テスト戦略が必要です。

コードをテストでカバーすることは素晴らしいことであり、コードの暗い部分がカバーされているほど、新しい機能を実装するときに安全に感じることができます。ただ、私の意見では、テストを書くのに費やした時間と比較して、テストがより多くの価値をもたらすバランスを見つける必要があります。たとえば、これは私のテスト戦略です。

  • ビジネス ロジック (サービス、リポジトリ、BLoC) は、ユニット/統合テストで 85 ~ 100% カバーする必要があります。これはアプリケーションの最も重要な部分であるため、そこでのテストには多くの価値があります。
  • ウィジェット テストは、再利用可能なすべての UI コンポーネントをカバーする必要があります。個々のコンポーネントが適切にテストされると、個々の画面のテストを開始できますが、詳細は少なくなります。
  • 主なアプリケーション フローと UI とのやり取りをカバーするエンド ツー エンド テスト。深いレベルのマジックはなく、いくつかの重要なワークフローを通過するだけです。含まれる画面が多いほど、優れています。
  • UI 全体の準備ができて実装されたら — UI が後で変更の影響を受けないことを確認するためのゴールデン テスト。

正直なところ、私はまだテストの黄金比を探していますが、プロジェクトを重ねるごとに上達していきます。信頼してください。

11. README ファイル

README を作成する ( source )

あなたは私の言うことを正しく聞きました — ドキュメンテーションです。README ファイルは、特にチームで作業する場合、プロジェクトの最も重要なドキュメントです。

コード生成を必要とする新しいソリューションを導入したばかりですか? プロセスを自動化するための新しい便利な bash スクリプトを追加しましたか? プロジェクトのどこでも使用しなければならないグローバル ロガーを実装しましたか? 私たちはあなたの心を読むことができません — README ファイルでそれを述べてください!

ドキュメントが多すぎるということはありません (少なくとも私はそのような状況にあったことはありません)。プロジェクトとコードに関する情報が不足しているだけです。コードを生成、テスト、実行するためのすべてのコマンド、さまざまなファイル構造の決定、図、外部ツールとサービス、さまざまな環境に関する情報 (シークレット キーなし) をここに配置し、1 か所に保管する必要があります。これは退屈な作業ですが、非常にやりがいのある作業です!

 

ふぅ、なんて乗り物だ…(ソース

それでおしまい!この記事を読んでいただきありがとうございます。

私は何か見落としてますか?コメントでそれについて言及してください!新しい Flutter アプリケーションを構築する際のチェックリストは何ですか?

ソース: https://medium.com/flutter-community/11-things-to-remember-for-your-next-flutter-project-1c7c380895ca 

#next #flutter 

次の Flutter プロジェクトで覚えておくべき 11 のこと
Duong Tran

Duong Tran

1660658400

11 Điều Cần Nhớ Cho Dự án Flutter Tiếp Theo Của Bạn

Tạo một dự án Flutter mới là một điều may mắn - codebase mới, không có mã kế thừa (chưa), null-safe, phiên bản mới nhất của các gói yêu thích của bạn, v.v. Nhưng đồng thời, bạn nên đưa ra các quyết định quan trọng khi bắt đầu dự án sẽ đặt nền tảng cho tương lai, chẳng hạn như công cụ, gói, cấu trúc tệp, giải pháp quản lý trạng thái, kế hoạch thử nghiệm. Nếu không, dự án cuối cùng sẽ chỉ trở thành một tô mì spaghetti và thịt viên khác. Để tránh điều này, tôi đã chuẩn bị một danh sách, theo quan điểm của tôi, các yếu tố quan trọng nhất của dự án nên được quyết định sớm. Do đó, tôi hy vọng nó sẽ giúp ích cho bạn - chúc bạn đọc vui vẻ!

1. Phân tích mã tĩnh

Tôi sẽ không viết mã lộn xộn ( nguồn )

Linter là một công cụ phân tích tĩnh xác định và gắn cờ các lỗi lập trình, cảnh báo, lỗi kiểu trong mã của bạn để bạn sửa chúng. Trong ngữ cảnh Flutter, đó là một trong những điều dễ thực hiện nhất và là một trong những điều hữu ích nhất để giữ cho mã của bạn sạch sẽ.

Có rất nhiều quy tắc khác nhau mà bạn có thể đặt để mã của mình tuân theo, nhưng tôi khuyên bạn nên sử dụng một trong các bộ được xác định trước đã tuân theo các phương pháp hay nhất dựa trên Hướng dẫn kiểu Dart :

Cho dù bạn chọn gói nào, bạn luôn có thể thêm hoặc xóa bất kỳ quy tắc phân tích tĩnh cụ thể nào trong tệp analysis_options.yaml .

2. Bản địa hóa (l10n)

Bản địa hóa ( nguồn )

Bản địa hóa ( ngắn gọn là l10n ) là gì?

Bản địa hóa là sự thích ứng của một sản phẩm hoặc dịch vụ để đáp ứng nhu cầu của một ngôn ngữ, văn hóa cụ thể hoặc "giao diện" của người dân mong muốn. - TechTarget

Điều cần thiết là phải xây dựng một ứng dụng tạo cảm giác tự nhiên cho người dùng, ví dụ như sử dụng các bản dịch phù hợp, định dạng ngày tháng và đơn vị tiền tệ, hướng văn bản. Vì vậy, bản địa hóa là một công cụ cơ bản để sử dụng. Ngay cả khi bạn đang xây dựng một ứng dụng khu vực / ngôn ngữ, tôi vẫn khuyên bạn nên triển khai bản địa hóa sớm, do đó tách văn bản của bạn khỏi mã giao diện người dùng. Do đó, chúng có thể được sử dụng lại cũng như điều chỉnh sau này mà không ảnh hưởng đến mã.

Tài liệu Flutter giải thích cặn kẽ quá trình quốc tế hóa ứng dụng của bạn. Nếu cách mặc định có vẻ quá phức tạp và / hoặc bạn cần một số tiện ích mở rộng và phương pháp trợ giúp hữu ích, thì có các gói bên thứ ba phổ biến, chẳng hạn như easy_localization , có thể giúp bạn trong quá trình bản địa hóa.

3. Môi trường (với một số hương vị)

Môi trường lập trình ( nguồn )

Tôi cá là bạn đã nghe ít nhất một trường hợp từ môi trường của mình (không có ý định chơi chữ) khi ai đó làm hỏng dữ liệu hoặc xóa toàn bộ bảng của người dùng trong sản xuất. Tin tôi đi - điều này không có gì vui cả. Do đó, bạn nên tạo các môi trường khác nhau cho dự án của mình:

  • Môi trường phát triển (cục bộ) - được sử dụng cho bạn: thực hiện các thử nghiệm trong mã, thay đổi dữ liệu trực tiếp trong cơ sở dữ liệu, thực hiện các phím tắt và mã hóa cứng mã thông báo xác thực hoặc cung cấp dữ liệu giả mạo. Hãy vui vẻ và cung cấp những tính năng đó!
  • Môi trường trung gian ( thử nghiệm hoặc phân giai đoạn ) - giúp bạn xác thực các thay đổi trong mã, thử nghiệm các tính năng với dữ liệu “thực” (thông thường, ảnh chụp nhanh dữ liệu sản xuất được sử dụng trong các môi trường như vậy) và xác minh ứng dụng trước khi phát hành nó vào phiên bản sản xuất . Nếu bạn có các kỹ sư QA trong nhóm của mình, đây là nơi để họ tỏa sáng.
  • Môi trường sản xuất - môi trường được sử dụng bởi người dùng thực, nơi dữ liệu bị hỏng là không thể chấp nhận được (vui lòng luôn thực hiện sao lưu).

Có những môi trường như vậy giúp bạn thử nghiệm và xác minh các tính năng một cách an toàn trước khi những thay đổi đó đến tay người dùng.

Bây giờ, một phần khác - hương vị . Không không, chúng tôi không nói về thứ gì đó ngọt, mặn hay chua - đó chỉ là một thuật ngữ khác được sử dụng trong lập trình để mô tả các biến thể xây dựng khác nhau cho ứng dụng của bạn. Ví dụ: bạn muốn đặt biểu tượng và tiêu đề, điểm cuối API hoặc bất kỳ cấu hình nào khác cho từng môi trường cụ thể. Vì vậy, bạn xác định một "hương vị" khác được sử dụng khi ứng dụng đang được xây dựng cho một môi trường cụ thể. Dưới đây là một số tài nguyên về cách tạo hương vị cho Flutter .

4. Tích hợp liên tục và phân phối liên tục (CI / CD)

Các giai đoạn tích hợp liên tục (CI) và phân phối liên tục (CD) ( nguồn )

Sau khi giới thiệu các môi trường khác nhau, bước tiếp theo tự nhiên là tự động hóa quá trình xây dựng, thử nghiệm và phát hành ứng dụng của bạn. CI / CD tự nó là một chủ đề khá phức tạp và tôi không phải là chuyên gia trong lĩnh vực này, do đó tôi khuyên bạn nên tìm kiếm một số tài nguyên khác về cách tự động hóa các giai đoạn phát triển ứng dụng khác nhau.

Tuy nhiên, có rất nhiều giải pháp NoOps tương thích với Flutter để bạn có thể tự động hóa quá trình phát triển của mình một cách dễ dàng:

Bất kỳ giải pháp nào trong số đó đều có tác dụng - chỉ cần chọn giải pháp phù hợp với nhu cầu và ngân sách của bạn.

5. Mã phụ trợ

Một lần nữa meme về phụ trợ ( nguồn )

Bạn đã triển khai chương trình phụ trợ của mình bằng bất kỳ ngôn ngữ lập trình kỳ lạ hoặc có thể không quá lạ mắt nào chưa? Tuyệt vời, bạn có thể bỏ qua bước này nhưng tôi vẫn khuyên bạn nên kiểm tra một số giải pháp đám mây để tham khảo trong tương lai.

Trong phiên bản đơn giản hóa, có hai tùy chọn cho phần phụ trợ của ứng dụng của bạn:

  1. Triển khai giải pháp phụ trợ tùy chỉnh bằng bất kỳ ngôn ngữ lập trình và khuôn khổ nào bạn thích, nhưng sau đó sẽ quan tâm đến tất cả các nội dung DevOps để làm cho mã và dữ liệu của bạn có thể truy cập được từ ứng dụng.
  2. Sử dụng bất kỳ giải pháp đám mây nào để tăng tốc quá trình phát triển và để hầu hết các DevOps hoạt động cho nhà cung cấp đám mây.

Trong trường hợp tùy chọn thứ hai có vẻ hấp dẫn với bạn, có một số nền tảng đám mây tuyệt vời để lựa chọn hỗ trợ Flutter:

Nền tảng đám mây cung cấp các tùy chọn xác thực, cơ sở dữ liệu, lưu trữ, API cho ứng dụng của bạn và nhiều tính năng khác. Bất kỳ cái nào trong số này đều là lựa chọn tuyệt vời khi bạn chỉ cần xác thực ý tưởng và xây dựng MVP nhanh chóng mà không cần tốn nhiều thời gian cho giải pháp phụ trợ toàn diện.

6. Ghi nhật ký, dữ liệu sự cố và phân tích

Rất tiếc, đã xảy ra lỗi ( nguồn )

Ghi nhật ký bị đánh giá thấp - đây, tôi đã nói rồi! Mọi thứ đều ổn cho đến khi xảy ra sự cố và bạn cần thông tin về điều đó. Luôn luôn có một vùng xám khi chúng ta thảo luận về những gì nên ghi nhật ký và những gì không. Nhưng có một điều luôn rõ ràng - bạn phải biết khi nào ứng dụng của mình gặp sự cố và nguyên nhân gây ra sự cố. Bạn càng thu thập được nhiều dữ liệu về sự cố, thì việc tìm kiếm và khắc phục sự cố càng trở nên dễ dàng hơn.

Các dịch vụ như Sentry , Firebase Crashlytics , Datadog có thể giúp bạn ghi lại các dữ liệu quan trọng nhất, báo cáo sự cố hoặc thậm chí thiết lập thông báo khi ứng dụng hoặc các dịch vụ liên quan của bạn gặp sự cố.

Một loại ghi nhật ký khác là thu thập dữ liệu người dùng cho các mục đích phân tích. Khi bạn đang xây dựng một sản phẩm mới, có thể là độc nhất, điều quan trọng là phải hiểu nhu cầu của người dùng, hành vi của họ và cách họ sử dụng ứng dụng. Đối với điều này, nhiều công cụ phân tích khác nhau có thể được tích hợp vào ứng dụng Flutter của bạn, chẳng hạn như Firebase Analytics , App Center Analytics và nhiều công cụ khác.

7. Thương hiệu ứng dụng

Chủ đề tài liệu ( nguồn )

Một trong những mục tiêu chính của bất kỳ ứng dụng hoặc thương hiệu nào là phải dễ nhận biết. Sử dụng đúng bảng màu, logo, biểu tượng, các yếu tố thiết kế, nội dung, phông chữ, đôi khi cả bố cục làm cho sản phẩm của bạn nổi bật hơn những sản phẩm khác. Đó là xây dựng thương hiệu ứng dụng , và việc chuẩn bị các phần cơ bản ngay từ đầu sẽ giúp bạn tiết kiệm rất nhiều thời gian trong toàn bộ dự án.

Nếu bạn đã có sẵn nguyên mẫu giao diện người dùng hoặc các thành phần thiết kế, bây giờ là thời điểm tốt để chuyển chúng sang ứng dụng của bạn và xác định chúng - màu sắc, phông chữ, hình dạng, v.v. Để dễ dàng hơn, một người tốt Mike Rydstrom đã tạo ra một gói nổi bật cho this - flex_color_scheme .

8. Cơ cấu dự án và quản lý nhà nước

Quản lý nhà nước trong Flutter ( nguồn )

Vâng, một trong những tranh cãi. Nói rõ hơn, không có cái gọi là “giải pháp quản lý nhà nước tốt nhất” hay “kiến trúc tốt nhất của ứng dụng” - nếu ai đó nói khác, hãy nhớ rằng họ cũng có thể đổ sữa vào bát trước ngũ cốc. Và đó là phần tồi tệ nhất - tôi không thể dạy bạn cách tốt nhất. Tôi chỉ có thể cung cấp một số tùy chọn hoặc chia sẻ sở thích của mình.

Một số tùy chọn cấu trúc tệp cho dự án Flutter tiếp theo:

  • Kiến trúc sạch - tách biệt rõ ràng các mối quan tâm, có trong một thời gian dài. Thành thật mà nói, tôi không phải là một fan hâm mộ của điều này. Tôi cảm thấy rằng có quá nhiều trừu tượng trong khái niệm này có thể làm chậm quá trình phát triển.
  • Kiến trúc phân lớp - dựa trên ý tưởng tách dữ liệu, kinh doanh và logic trình bày thành các lớp riêng biệt. Cấu trúc tệp như vậy hoạt động tốt cho các dự án vừa và nhỏ, nhưng tôi cảm thấy rằng các lớp này ngày càng trở nên quá tải khi dự án phát triển.
  • Kiến trúc mô-đun (tôi đã mô tả khái niệm này ở đây ) - tách mã thành các mô-đun cho mỗi tính năng trong đó các mô-đun khác nhau tương tác. Đây là giải pháp yêu thích của tôi - nó hoạt động trơn tru với giải pháp quản lý nhà nước BLoC (TEAM BLOC, YEAH!), Quy mô tốt cho các dự án lớn. Tuy nhiên, nó mang lại một số thách thức, như đặt logic chung ở đâu, các mô-đun khác nhau nên giao tiếp như thế nào, v.v.

Về quản lý nhà nước ở Flutter - tôi nghĩ rằng chúng ta đang ở thời điểm có thể dành toàn bộ hội nghị cho chủ đề này và vẫn chưa có câu trả lời cuối cùng sau đó. Chỉ cần thêm hai xu của tôi, hãy chọn một đồng mà bạn cảm thấy thoải mái nhất. Bạn có thể tìm thấy một danh sách đầy đủ các tùy chọn ở đây .

9. Tạo mã

Tạo mã ( nguồn )

Nếu bạn muốn cắt một số góc và tiết kiệm thời gian phát triển, bạn có thể sử dụng tạo mã trong dự án của mình. Mã ít hơn, cung cấp nhiều hơn !

Có một loạt các công cụ khác nhau để sử dụng, cho dù làm việc với bản địa hóa, nội dung, phân tích cú pháp JSON, tạo các lớp mô hình, triển khai bộ định vị dịch vụ, định tuyến hoặc làm việc với các trạng thái bất biến. Điều duy nhất cần làm là điều tra các công cụ và gói có sẵn và chọn những công cụ và gói tốt nhất để đáp ứng nhu cầu dự án của bạn.

Để khởi động dự án Flutter nhanh chóng, tôi khuyên bạn nên kiểm tra CLI Rất Tốt . Nó sẽ giúp bạn tiết kiệm vài giờ cấu hình (thật không may, tôi đã học nó một cách khó khăn).

Ngoài ra, tháng trước tôi đã nói chuyện về việc tạo mã - nó có thể là điểm khởi đầu cho hành trình tạo mã Flutter của bạn, vì vậy hãy kiểm tra điều đó!

10. Chiến lược kiểm tra

Thử nghiệm ứng dụng ( nguồn )

Việc kiểm tra 100% mã của bạn là tốt hay xấu? Chắc chắn, nó thật tuyệt vời, nhưng với chi phí nào? Nghĩ theo cách này, bạn có thể rơi vào hố sâu cam go, nơi bạn dành nhiều thời gian để viết các bài kiểm tra hơn là phát triển các tính năng. Để tránh điều này, bạn cần một chiến lược thử nghiệm.

Đừng hiểu lầm tôi - che mã của bạn bằng các bài kiểm tra là một điều tuyệt vời và càng che được nhiều chỗ tối của mã, bạn càng cảm thấy an toàn hơn khi triển khai các tính năng mới. Chỉ là, theo ý kiến ​​của tôi, bạn nên tìm thấy điểm cân bằng mà các bài kiểm tra vẫn mang lại cho bạn nhiều giá trị hơn so với thời gian dành cho việc viết chúng. Ví dụ, đây là chiến lược thử nghiệm của tôi:

  • Logic nghiệp vụ (dịch vụ, kho lưu trữ, BLoC) nên được bao phủ 85-100% trong các bài kiểm tra đơn vị / tích hợp - đây là phần quan trọng nhất của bất kỳ ứng dụng nào, vì vậy tôi thấy rất nhiều giá trị trong các bài kiểm tra ở đó;
  • Kiểm tra tiện ích sẽ bao gồm tất cả các thành phần giao diện người dùng có thể sử dụng lại. Khi các thành phần riêng lẻ được kiểm tra đúng cách, bạn có thể bắt đầu kiểm tra từng màn hình nhưng ít chi tiết hơn.
  • Các bài kiểm tra từ đầu đến cuối , bao gồm các luồng ứng dụng chính và các tương tác với giao diện người dùng. Không có phép thuật cấp độ sâu - chỉ cần trải qua một số quy trình công việc quan trọng. Chúng càng bao gồm nhiều màn hình thì càng tốt.
  • Khi toàn bộ giao diện người dùng đã sẵn sàng và được triển khai - các bài kiểm tra vàng để đảm bảo rằng giao diện người dùng không bị ảnh hưởng bởi các thay đổi sau này.

Thành thật mà nói, tôi vẫn đang tìm kiếm ý nghĩa vàng đó trong thử nghiệm, nhưng bạn sẽ trở nên tốt hơn ở dự án này đến dự án khác, hãy tin tôi.

11. Tệp README

Tạo README ( nguồn )

Bạn đã nghe tôi nói đúng - tài liệu hướng dẫn. Tệp README là tài liệu quan trọng nhất của dự án, đặc biệt là khi làm việc nhóm.

Bạn vừa giới thiệu một giải pháp mới yêu cầu tạo mã? Bạn vừa thêm một tập lệnh bash hữu ích mới để tự động hóa quy trình? Bạn đã triển khai trình ghi nhật ký toàn cầu PHẢI được sử dụng ở mọi nơi trong dự án chưa? Chúng tôi không thể đọc được suy nghĩ của bạn - hãy đề cập đến điều đó trong tệp README!

Không có cái gọi là quá nhiều tài liệu (ít nhất là tôi chưa từng ở trong tình huống như vậy) chỉ thiếu thông tin về dự án và mã. Tất cả các lệnh để tạo, kiểm tra và chạy mã, các quyết định cấu trúc tệp khác nhau, sơ đồ, các công cụ và dịch vụ bên ngoài, thông tin về các môi trường khác nhau (KHÔNG CÓ BÀN PHÍM BÍ MẬT) nên được đặt ở đây và lưu giữ ở một nơi duy nhất. Đây là một công việc nhàm chán nhưng là một công việc rất bổ ích!

 

Phew, thật là một chuyến đi… ( nguồn )

Đó là nó! Cảm ơn bạn đã dành thời gian đọc bài viết này.

Tôi đã bỏ lỡ điều gì đó? Đề cập đến điều đó trong các ý kiến! Danh sách kiểm tra của bạn trong khi xây dựng một ứng dụng Flutter mới là gì?

Nguồn: https://medium.com/flutter-community/11-things-to-remember-for-your-next-flutter-project-1c7c380895ca

#next #flutter 

11 Điều Cần Nhớ Cho Dự án Flutter Tiếp Theo Của Bạn

Windows11: Windows 11 Made using NextJS and Tailwind CSS

Windows 11

Windows 11 made with 💛 using NextJS and TailwindCSS by Vishwa Gaurav.

ScreenShots

01 02 03

*In Development Mode

Our Social Links

LinkedIn Twitter

PageSpeed Insights

Tech Used

Next JS React JavaScript TailwindCSS CSS3 HTML5 Vercel

Contribute

If you are Using NPM then:

  • Step 1: Fork and Download the Repository
  • Step 2: Open it in editor like VSCode
  • Step 3: Open Terminal inside it and run npm install to install required dependencies (you can apply '--force' after command and then run it , incase you face any error)
  • Step 4: Run npm run dev to launch the website on 'localhost:3000' and check if it is working without any error.
  • Step 5: Do your Changes and make sure that you don't get any error or warning.
  • Step 6: Push on github and Create a Pull Request

Stuck? Search your issue/error on Google

You can SPONSOR us

NextJS Guide

This is a Next.js project bootstrapped with create-next-app.

Getting Started

First, run the development server:

npm run dev
# or
yarn dev

Open http://localhost:3000 with your browser to see the result.

You can start editing the page by modifying pages/index.js. The page auto-updates as you edit the file.

API routes can be accessed on http://localhost:3000/api/hello. This endpoint can be edited in pages/api/hello.js.

The pages/api directory is mapped to /api/*. Files in this directory are treated as API routes instead of React pages.

Learn More

To learn more about Next.js, take a look at the following resources:

You can check out the Next.js GitHub repository - your feedback and contributions are welcome!

Deploy on Vercel

The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.

Check out our Next.js deployment documentation for more details.


Author: VishwaGauravIn
Source code: https://github.com/VishwaGauravIn/windows11
License:  Apache-2.0 license
#react-native #javascript #next #tailwindcss 

Windows11: Windows 11 Made using NextJS and Tailwind CSS

Frontend Build with React Next.js for View Service User With Express

Frontend Service Users

Project ini saya buat dengan Next.js, React hook, Tailwind, Daisy, Typescript dan Axios

Cara memulai dan menjalankan project

  • Lakukan git clone https://gitlab.com/ferdianar/privy-frontend.git
  • Masuk direktori project dan Install dependencies menggunakan npm Install

Merubah PORT sesuai config PORT di backend

Berikutnya untuk merubah PORT backend sesuai config env backend, masuk ke Folder Pages, yang perlu dirubah port nya di file

  • Profile.tsx untuk profile endpoint, terus masuk folder
  • auth/register.tsx untuk register,
  • auth/login.tsx untuk login, dan di folder
  • component/navbar.tsx untuk ngerubah port endpoint logout

Kalau sudah, jalankan dengan perintah npm run dev

Otomatis akan berjalan di port 3000. akan tampil halaman index dan progress bar akan berjalan sampai penuh, otomatis akan diredirect ke halaman login.

Mendaftar User

Jika belum ada user di database, bisa daftar ke hamburger profile kanan atas dan pilih register password yang dimasukkan harus cocok, kalau tidak cocook akan mengeluarkan errror "password tidak cocok" dan email harus terisi, Jika tidakk akan mengeluarkan error "email wajib diisi"

kalau sudah terisi semua, register. dan otomatis kalau sukses di arahkan ke halaman login

Login User

Masukkan email dan password sesuai di database Kalau sudah login, diarahkan ke menu profile, data lainnnya null, jadi kosong, untuk menu setting update nya masih belum karena saya ada gangguan di minggu minggu ini, jadi untuk menge test nya bisa mengupdate manual di mysql phpmyadmin, kecuali kolom cover dan phooto.

kalau sudah terisi, reload halaman profile , otomatis data akan tampil otomatis. sesuai data di database

Logout Users

Untuk log out klik kanan atas profile Klik Logout, otomatis refresh token akan di cleardari cookies, dan diredirect ke halaman login. sehingga kalau masuk ke halaman profile lagi, akan ditolak, dan diredirect ke halaman login lagi.

Preview Halaman Home ketika dijalankan pertama kali

Judul halaman di atas akan otomatis tampil sesuai kondisi halaman. Kalau sedang di homepage, akan tampil Homepage Dan karena awal user belum login, jadi untuk nama user di pojok kanan atas masih undefined karena tidak terdeteksi access token yang valid. previewhome

Preview Halaman Profile

Jika sudah sukses login, akan tampil seperti ini. Nama user di pojok kanan atas otomatis ter update. Sesuai access token preview

Letak tombol log out untuk mengakhiri sesi dan refresh token

Halaman Profile di required untuk login dahulu, jadi ketika sudah logout , masuk ke profile lagi akan ditolak logout

Mobile Friendly, menggunakan Tailwind CSS, Daisy + Grid

Karena selalu suka mobile version, jadi tidak lupa untuk responsive nya 
mobile

Thank You ..... Greeting from Ferdian Ahmad R


Author: ferdianar
Source code: https://github.com/ferdianar/frontend-service-users

#react-native  #typescript  #javascript #next 

Frontend Build with React Next.js for View Service User With Express
Marisol  Kuhic

Marisol Kuhic

1660287600

Hulu App: A Hulu Clone App Developed with Nextjs & Tailwindcss

Hulu App

This is a Next.js project bootstrapped with create-next-app.

A Hulu Clone App developed with Nextjs & Tailwindcss

Get a preview at:

alt text

API

Getting Started

First, run the development server:

npm run dev# oryarn dev

Open http://localhost:3000 with your browser to see the result.

You can start editing the page by modifying pages/index.js. The page auto-updates as you edit the file.

API routes can be accessed on http://localhost:3000/api/hello. This endpoint can be edited in pages/api/hello.js.

The pages/api directory is mapped to /api/*. Files in this directory are treated as API routes instead of React pages.

Learn More

To learn more about Next.js, take a look at the following resources:

You can check out the Next.js GitHub repository - your feedback and contributions are welcome!

Deploy on Vercel

The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.

Check out our Next.js deployment documentation for more details.


Author: realvincentuche
Source code: https://github.com/realvincentuche/hulu-app
 

#javascript #react-native #tailwindcss #next 

Hulu App: A Hulu Clone App Developed with Nextjs & Tailwindcss