Related articles and reading order

1. Initialize the project

2. Improve the development experience

3. Organize projects and miscellaneous

4. Package the project

5. Team specifications

The project address

preface

In the last article about improving development experience, we integrated a bunch of plug-ins and functions all at once, which led to the confusion of the project structure. The key problems are in the build folder of webpack’s relevant configuration items. Therefore, today’s work is relatively easy, the focus is to organize the project structure, and then add some miscellaneous items.

  1. Organize the project structure
  2. integrationAnt DesignAnd make theme changes
  3. Consolidate common functions and have all components inherit them
  4. integrationmobxManage project status
  5. usereact-hot-loaderHeat loading
  6. integrationsvg-component

Organize the project structure

While doing this, let’s first take a look at the current project structure:

build
webapck

The first thing you need to decide when doing this is, what are we going to do with the WebPack configuration directory? To determine this, just take a look at what configuration is in WebPack, and then divide the modules according to each configuration item:

entry
output
resolve

  • First of all topluginsRelated content moved out:
  1. First of all inbuildCreate a new file inplugins.jsThen copy the code from the original plugin:
  2. inwebpack.config.jsLt.plugins.jsEnter the content of:
  • Integration path selection in webpack.config.js you’ll see many places where path.join is used, and this block can also be extracted as a tool module. Create a new build/utils.js file and write the following code to target the path to the root directory, passing the detailed path as an argument:

    Then use this function wherever it is needed:

  • The module item contains many related configurations, including loader for TS (x), SCSS and other related files, and loader for image and other file types will be added later, so this section needs to be divided into more details:

  1. inbuildIn the newrulesDirectory, inside the newjsRulesandstyleRulesFile:
  2. Before themoduleLoader configuration as in the corresponding file and export, and then inwebpack.config.jsThe first isjsRulesContent:

    And then thestyleRulesContent:

    And finally, after the introduction of ruleswebpack.config.js:

Now that we have separated the webPack configuration items, we integrate the Ant DesignUI library (ANTD for short) and change its theme colors.

Integrated antd

  • Integrating ANTD is very simple, just NPM install -s antd, and then we introduce one of the components in the Components /Test component:

    You’ll find it already works:

  • In the development of ANTD, the color scheme we use is not antD’s original color scheme. If a large number of ANTD components are used, it is really troublesome to modify the color scheme one by one, so it is necessary to modify the theme color of ANTD at a time.

  1. antdUsing the style oflessTo write, the modification to its theme is also to thelessVariable to change, so you need to install to change the themelessandless-loader: npm install -D less less-loader
  2. Then we add one in the root directorytheme.jsFile, which is the theme style code that needs to be modified, what specific theme can be modified can be clickedhereTo view:
  3. And then write it inbuild/rules/styleRulesTo add the targetlessImport the theme file from the previous step:
  4. And we ended up incomponents/TestComponent introductionButtonComponent styleslessFile:

    At this point, you can view the effect and find that the theme has been modified successfully:

  5. Problems: There are still some problems with the antD component import and theme modification steps at this time, such as importing a component and manually importing its correspondinglessFile, this is a very troublesome thing, so we need to solve the problem of importing antD components at the same time also automatically importing its correspondinglessFile. Also, useimport {Button } from 'antd'One of the major drawbacks of this approach is that introducing one of the components will bring out the wholeantdFiles are coming in, it’s slowing down the build speed, and it gets bigger when you pack it up, so we still have to do thatantdLoad on demand. So we need to solve these two problems, and these two problems can be solved simultaneously.
  • Antd is loaded on demand
  1. inantdIt is recommended on the official websitebabel-plugin-importTo do on-demand loading, but our project usestypescript, is to goawesome-typescript-loaderCompile, so in our projectbabel-plugin-imporIt doesn’t work, so you need something calledts-import-pluginThe plug-innpm install -D ts-import-plugin
  2. Step two we need to be inbuild/rules/jsRules.jsIs configured according tots-import-pluginThe tutorial can be directly configured:
  3. Go back toTestThe component will beimport 'antd/lib/button/style/index.less'Delete this sentence and run it again to see the effect:

Integrating common functions

In the previous step, we integrated antdUI library. There are many common things in this library, such as message component and notification component, but these two components have to be introduced if they are used frequently. When they are used frequently, we can consider integrating them into a React component. All components inherit from the React component. The advantage of this is that when common libraries such as Axios are added, the react component can also be incorporated into the react component, so that all components that inherit from the React component can use it.

  • Integrating common functions
  1. We first insrcUnder the newutilsDirectory, and then inutilsIn the newreactExt.tsxFile:
  2. Then, intsconfig.jsonIn the setutilsTo facilitate future path references:
  3. inreactExt.tsxThe introduction ofantdCommon components, and then export this component that incorporates antD components. Of course, you can also call it a class, which is important because every react component will use antDcomponentExtAnd here we need to use typescriptinterfaceThe React componentstateandpropsRestrict the data type, but at the same time you don’t know what each React component is targetingstateandpropstheinterfaceHow is it, so incomponentExtIs needed inThe genericTo manyinterface:
  4. Finally, incomponents/TestComponent introductioncomonentExtTest:

    In the future, if there are commonly used functional functions, you can also go tocomponents/reactExtTo add.

Integrated mobx

Mobx is an excellent state management tool in the React stack. It has the function of monitoring data and is more convenient than Redux. It can also be used independently without React. Install NPM install -s mobx-react. Let’s test mobx with a classic calculator component.

  • Before testing, we also need to tidy up the directory where the components are stored. First, differentiate the role of the component directory.
  1. componentsA directory is used to store generic components that do not contain any business functionality.
  2. newsrc/containers/viewsDirectory, which is used to hold business components that cannot be reused.
  3. newsrc/containers/sharedDirectory, which is used for storageYou can reuseBusiness components of.
  4. intsconfig.jsonTo set a short path for later call:

    This step doesn’t play much of a role in this blog, but it does work well for the organization of real projects. The diagram below:

  • Create the store
  1. newsrc/storeDirectory for storagestoreFile and create a new one under that directoryglobalStoreAnd the contents ofindex.tsxFile:
  2. And then in thisindex.tsxThe file has the following code: whereobservableandactionPlease check the functionmobxDocuments:
  3. Then the newsrc/store/index.tsxFiles are used to export these stores:
  • React/SRC /index.tsx: SRC /index.tsx: SRC /index.tsx: SRC /index.tsx

    Here belowconfigure({enforceActions: 'observed'})Used to restrict beingobservable(That is, added to store@observable), so that it can only be added@actionIs modified in the function.

  • Write the Counter component to test

  1. We went tosrc/containers/viewsIn the directory, addedCounter/index.tsxAnd write the following code:
  2. Then use this componentmobx-reactBecomes observable and uses@injectinjectionglobalStore:
  3. And we ended up insrc/index.tsxThe introduction ofCounterComponent, and take a look at itpropsIs there any data in:
  4. Finally back toCounterThe authoring method in the component checks whether the function is normal:
  • Add global typescript validation to store. In the example above, although we have functionally worked properly, it is obvious that there is an error because the component is not specifiedpropsThe validation interface causes typescript to assume thatglobalStoreIt’s not there. We can solve the problem by writing the following code:

    But each introducedglobalStoreThe components all need to be written once, so we can putIGlobalStoreThe verification interface is written as the global verification interface and can be directly verified in the form of the following figure:

    The steps are as follows:

  1. We are insrc/store/globalStoreUnder the newtype.d.ts:
  2. Go to theglobalStore/index.tsx,GlobalStoreClass export, which we will use as a typescript validation interface (You can see more about this usage here) :
  3. intype.d.tsClass, and then define and export a global namespace (The usage is explained here), and then export the interface from the namespace:
  4. Go back toCounterIn the component, rewrite the interface as follows:

    Note the need to add?Because this attribute is taken from the store, the parent component will report an error saying that the value was not passed. But because of the addition?So thisglobalStoreVerify that there is not necessarily one, which results in the following error in the component:

    We can go at this timetsconfig.jsonLt.strictNullChecksA place forfalseTo remove thenullandundefinedCan be detected:

  5. At this point we have successfully integrated Mobx and added typescript validation for Store:

usereact-hot-loaderHeat loading

This step is mainly aimed at webpack-dev-server’s automatic page refresh function does not keep the data always, sometimes it is inconvenient to keep the data unchanged after updating the component code. Therefore, in this case, react-hot-loader is needed to detect page code changes and find the changed parts for updating, while ensuring the same data.

  1. First we install itnpm install -D react-hot-loader
  2. And then we’re going to use what’s in itreact-hot-loader/babelBut because we useawesome-typescript-loader, so you don’t need to add it in the root directory.babelrcThe file. Go straight inbuild/rules/jsRules.jsTo configure:
  3. And then we go toCounterComponent introductionreact-hot-loaderIn thehotMethod to wrap the component directly as a decorator:
  4. Finally, topackage.json, in thedevCommand followed by--hotYou can:
  5. Go back toCounter< span style = “box-sizing: border-box; color: RGB (74, 74, 74); display: block; line-height: 22px; font-size: 14px! Important; word-break: break-all;

    In fact, we’ve already succeeded when we see this output on the console:

integrationsvg-component

In front end development, SVG images are used very frequently, but with the integration of SVG-Component, we can import SVG images as components and use them:

  1. To be integratedsvg-componentWe have to install it first@svgr/webpack: npm install -D @svgr/webpack, this is a loader;
  2. And then we hadbuild/rulesIn the newfileRules.jsThe file will besvgFormat files are compiled with this loader:

    Then, inwebpack.config.jsonTo import and restart the project:

  3. And then we’re going to pick a random onesvgFormat pictures inCounter, but it also results in a typescript error saying the module could not be found:

    The reason for this error is that SVG images are not modular and do not provide module export, so they cannot be recognized when imported. To solve this problem, we can imitate the previous usecss moudlesGive it a module declaration: we are intypingsCreating a Directorysvg.d.tsFile and write the following code:

    This time can also besvg-componentWe declare an interface and then use that interface as content in the declared module:

    This interface usesreactStateless component declaration, the attributes passed in are the attributes of the SVG file such ascolor widthAnd so on, and then we can use it happilysvg-comonentA:

Now that we’ve sorted out the Webpack directory and added some libraries or tools with various functions, the next step will be dealing with the packaging part of the project.