Warehouse address: gitee.com/dreamer2011…

1, the preface

This project applies to the React project of mixed development of MOBILE terminal H5. Its functions include:

  1. The VW,Automatic font adaptationBy default, follow the UI design draft750 * 1334(The original size of UI draft can be configured in Webpack) up and down for various mobile devices;
  2. Automatically generatespriteSprite and relatedsprite.less, no need to manually create Sprite images and handwritten less;
  3. Webpack4 latest build, separate compressed code, remove repeatedly referenced CSS code, the development environment generates sourceMap for easy debugging, the production environment removes console.log print information and other builds, and generates correlationGz package, optimize page resource loading;
  4. Based on native APIFetch encapsulates the dataService serviceUnified format for GET and POST requests of related interfaces;
  5. Unified encapsulation of intermediate interception componentsFetchData.jsxTo perform component data preloading and state injection;
  6. React router componentsforLazing loadwithComponent preloading loadingandLoading failed error message, add page friendly prompt, performance is more optimized;
  7. Bebel7 configuration;
  8. configurationliveServerPre-run check on generated PROD production environment code;
  9. CSS image related optimization, CSS file production environment automatic separation;
  10. usingbrowserHistoryRouting mode. Local environment configurations are automatically configured (configured on the server when onlinenginx)
  11. Automatically generateFolder to save the current package generatedThe tar packagesTo prevent online deployment failures. If you have a backup, you can roll back the previous code version.
  12. If the relevant APP H5 Settings are omitted, it can be regarded as a PC project, compatible with IE9 +;
  13. increaseMobile debugging panel, function is equivalent to opening the PC console, you can easily view the console, network, cookies, localStorage and other key debugging information;
  14. Add gesture libraries such as Drag (Pan), Pinch (Pinch), Rotate (Rotate), swipe (swipe);
  15. increaseSentry monitoring code exceptions are reportedTo [email protected] / 1729437, check the newspaper…
  16. Bundle build completion reminders and buildsBundle Analysis Report Report

2. Command line

Local Server:

yarn dev 
#or
npm run dev
Copy the code

Build bundle:

yarn build
#or
npm run build
Copy the code

Generate the tar packages

#The default output is cdn.tar.gz
yarn tar
#or
npm run tar

#You can customize the name of the tar package
yarn tar react
#or
npm run tar react
Copy the code

Test packaged code to go live:

yarn start
#or
npm run start
Copy the code

3, modify the UI draft size original matching size

webpack.config.js

{
    test: /\.less$/.use: [
            isProduction ? MiniCssExtractPlugin.loader : 'style-loader'.'css-loader'.'less-loader'.// Configure the relevant mobile VW layout
            {
                loader: 'postcss-less-loader'.options: {
                    ident: 'postcss'.plugins: (a)= > [
                        postcssPxToViewport({
                            viewportWidth: 750.// (Number) The width of the viewport.
                            viewportHeight: 1334.// (Number) The height of the viewport.
                            unitPrecision: 3.// (Number) The decimal numbers to allow the REM units to grow to.
                            viewportUnit: 'vw'.// (String) Expected units.
                            selectorBlackList: ['.ignore'.'.hairlines'].// (Array) The selectors to ignore and leave as px.
                            minPixelValue: 1.// (Number) Set the minimum pixel value to replace.
                            mediaQuery: false // (Boolean) Allow px to be converted in media queries.}}]}Copy the code

4. How to generate Sprite image automatically

webpack.config.js

// Integrate the image into Sprite image
const SpritesmithPlugin = require('webpack-spritesmith');
// customerTemplate
const templateFunction = function(data) {
    // console.log('---', data)
    const shared = `.sprite_ico { background-image: url(I); display:inline-block; background-size: Wpx Hpx; } `
        .replace('I', data.sprites[0].image)
        .replace('W', data.spritesheet.width)
        .replace('H', data.spritesheet.height);

    const perSprite = data.sprites
        .map(function(sprite) {
            return `.sprite_ico_N { width: Wpx; height: Hpx; background-position: Xpx Ypx; } `
                .replace('N', sprite.name)
                .replace('W', sprite.width)
                .replace('H', sprite.height)
                .replace('X', sprite.offset_x)
                .replace('Y', sprite.offset_y);
        })
        .join('\n');

    return "//out:false" + '\n'+shared + '\n' + perSprite;
};
 / / Sprite

plugins.push(
    new SpritesmithPlugin({
        src: {
            // The following path is configured according to your actual path
            cwd: path.resolve(__dirname, './src/assets/icons'),
            glob: '*.png'
        },
        // Output Sprite image file and style file
        target: {
            // The following path is configured according to your actual path
            image: path.resolve(__dirname, './src/assets/sprite.png'),
            css: [
                [
                    path.resolve(__dirname, './src/less/sprite.less'),
                    {
                        format: 'function_based_template'}]]// css: path.resolve(__dirname, './src/less/sprite.less')
        },
        // Customize the template
        customTemplates: {
            function_based_template: templateFunction
        },
        // Call Sprite address writing in the style file
        apiOptions: {
            // This path is configured according to the page
            cssImageRef: '.. /assets/sprite.png'
        },
        spritesmithOptions: {
            // algorithm: 'top-down'
            padding: 5}}));Copy the code

The icon format should be PNG. Place the small icon to generate Sprite images under the directory SRC/Assets/ICONS, and then execute Yarn Build to find the className of your icon icon under SRC \less\sprite.less. Such as:

To use sprite_ico sprite_ICo_guzhi, use sprite_ico_guzhi. No configuration is required to import the sprite.less file;

<span className="sprite_ico sprite_ico_guzhi"></span>
Copy the code

React write specifications

The React component must start with a capital letter. For details, see the official website

6. Read the current file directory

CDN -- -- -- -- -- -- -- -- -- -- -- -- -- -- build the resources after the public -- -- -- -- -- -- -- -- -- -- -- -- -- -- static resource SRC -- -- -- -- -- -- -- -- -- -- -- -- -- -- all the React resources actions -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- action related to assets -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- all static image resources components -- -- -- -- -- -- -- -- -- -- -- -- the public component dataService -- -- -- -- -- -- -- -- -- -- - the request service less -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- less file pages -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- all entry documents under a file reducers -- -- -- -- -- -- -- -- -- -- -- -- -- -- reducer for the router -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - routing set store -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- state storage Utils ----------------- public method..... All the rest is App. JSX login. JSX entry documents such as tar -- -- -- -- -- -- -- -- -- -- -- -- -- -- build backup tar...Copy the code

7. Sentry exception code monitoring

index.html

<script src="https://cdn.ravenjs.com/3.26.4/raven.min.js" crossorigin="anonymous"></script>
/ / code error monitoring Raven. Config (' https://[email protected]/1729437 '). Install ();
Copy the code

Add the ==React ErrorBoundary== component, please refer to the official documentation:

import React from 'react'; import oops from "@assets/oops.png"; // catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { error: null }; } componentDidCatch(error, errorInfo) { this.setState({ error }); Raven.captureException(error, { extra: errorInfo }); } render() { if (this.state.error) { //render fallback UI return ( <div className="snap" onClick={() => Raven.lasteventid () && Raven.showReportDialog()}> <img SRC ={oops} /> <p>We're sorry -- something's gone wrong.</p> <p>Our  team has been notified, but click here fill out a report.</p> </div> ); } else { //when there's not an error, render children untouched return this.props.children; } } } export default ErrorBoundary;Copy the code

At this point, if we now intentionally change something wrong, the fallback UI will be prompted:

Click on the text, the user can send an issue to us:

Currently error messages are uploaded to sentry. IO, or you can create your own private server;

8. Eruda Mobile debugging panel

index.html

// View console resources on the mobile terminal
(function () {
    // CDN loading is recommended
    const src = 'https://cdn.jsdelivr.net/npm/[email protected]/eruda.min.js';
    // var src = 'node_modules/eruda/eruda.min.js';
    if (!/debug=true/.test(window.location) && localStorage.getItem('debug') != 'true') return;
    document.write('<scr' + 'ipt src="' + src + '"></scr' + 'ipt>');
    document.write('<scr' + 'ipt>eruda.init();  + 'ipt>'); }) ();Copy the code

Start the project, visit http://192.168.1.100:3002/? Debug =true on the phone as shown:

Hammer Gesture library

<script src="https://hammerjs.github.io/dist/hammer.js"></script>

Copy the code

For example:

import React from 'react';

class HammerPan extends React.Component {
    render() {
        return <div className="myElement">888</div>;
    }

    componentDidMount() {
        const myElement = document.querySelector('.myElement');
        // create a simple instance
        // by default, it only adds horizontal recognizers
        const mc = new Hammer(myElement);

        // let the pan gesture support all directions.
        // this will block the vertical scrolling on a touch-device while on the element
        mc.get('pan').set({ direction: Hammer.DIRECTION_ALL });

        // listen to events...
        mc.on('panleft panright panup pandown tap press', ev => {
            myElement.textContent = ev.type + ' gesture detected.';
        });
    }
}

export default HammerPan;


Copy the code

Start the project, visit http://192.168.1.100:3002/pan to view

10. Generate analysis Report

# NPM
npm install --save-dev webpack-bundle-analyzer
# Yarn
yarn add -D webpack-bundle-analyzer

Copy the code
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
}

Copy the code

11. The bundle generates a tar package and backs it up

package.json

"scripts": {
        "dev": "webpack-dev-server --mode development",
        "build": "bash ./rm.sh && webpack --mode production --profile --json > stats.json && yarn tar",
        "start": "node ./server.js",
        "tar": "bash ./tar.sh"
    }

Copy the code