In recent days, I developed a problem renderer (support to submit answers), the content is easy to write, from 0️ to build an environment for development and release is not easy 😭, so I sorted out an article to make a note.

This article records the construction, development and release process of the project, the project source address: Github.

There are a number of optimizations currently available, such as adding ESLint, tests, NPM publish hooks, etc.

The development of component

Since the components are relatively simple, the order of the article is to assume that the simple components are already written, then add what is needed, and work through the various extensions step by step. It’s not about setting up an environment to plug in extensions and then writing components when everything is ready. It is felt that the narrative of this article has a deeper understanding of the use of various extensions.

Building a development environment

Create the project directory and enter the execute command:

$ yarn init
Copy the code

After filling in a few options, a package.json is generated that contains basic information about the project.

Install the React

$ yarn add react react-dom
Copy the code

Develop component code

├ ─ SRC / / used to store the component source | ├ ─ index. The ts / / entry documents, used to expose component | ├ ─ utils. Ts | ├ ─ declaration file types / / ts | | ├ ─ externals. Which s / / because the project USES the less, Take additional statement to use modular import less file | | └ index. The ts | ├ ─ the Renderer | | ├ ─ index. The less | | └ index. The TSXCopy the code

The source code for the component is simple and not the focus of this article, so I won’t expand on it. See the project components section for the source code.

Installing and Configuring the TS

Since TS is used, the next step is to compile the TS file after writing the component.

#Because TS is only used in the development environment, it is installed in devDependencies
$ yarn add -D typescript
Copy the code

You need to create a new tsconfig.json configuration file at the root/directory of your project so that you don’t have to enter complex commands repeatedly each time you compile.

Json {"compilerOptions": {"outDir": "./dist", // output directory "module": "CommonJS", // specify which module system code to generate: "None", "CommonJS", "AMD", "System", "UMD", "ES6" or "ES2015" "target": "ES2015", // Specify ES target version, default ES3 "JSX ": "React ", // support JSX "declaration": true in.tsx files, // generate the corresponding.d.ts file "removeComments": true, // remove all comments, except for /! * Copyright information at the beginning. }, "include:" ["/SRC / * * *, / / need to compile the file], "exclude" : [" node_modules], "files" : []}Copy the code

Files imported using include can be filtered using the exclude attribute. However, files explicitly specified by the files attribute will always be included, regardless of the exclude setting. Exclude excludes node_modules, BOWER_Components, jSPM_Packages, and

directories by default if not specified.

About tsconfig. Json more configuration instructions, to view: www.tslang.cn/docs/handbo…

Developing an example

In order to facilitate development, we can create an Example (demo) in the current project. Instead of compiling and packaging components and referencing the compiled code, we can directly reference the source code of the renderer. In this way, after saving every modification, it can be automatically updated to the page, greatly improving the development efficiency. When development debugging is complete, production mode can be used so that the packaged, compiled and compressed renderer code can be used directly.

How to use: import/SRC /.. from example The component in.

The directory structure for the renderer example is as follows:

├ ─ example / / sample code | ├ ─ SRC | | ├ ─ index. The HTML / / used to mount the components to the page | | ├ ─ index. The TSX | | └ mock. Ts / / mock dataCopy the code

For the code, see: example

The introduction of webpack

Use Webpack to complete the package compilation of the project and open Example.

#Use webpack-dev-server to start local server example
$ yarn add -D webpack webpack-cli webpack-dev-server

#All kinds of loader
$ yarn add -D ts-loader less-loader style-loader css-loader
Copy the code

Create the configuration file webpack.config.js in the project root/for package compilation.

// webpack.config.js
// TODO is just a setup for the development environment
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const base = {
  mode: process.env.NODE_ENV === 'production' ? 'production' : 'development'.devtool: 'cheap-module-source-map'.resolve: {
    // Add '.ts' and '.tsx' as resolvable extensions.
    extensions: ['.ts'.'.tsx'.'.js'.'.json'],},module: {
    rules: [
      // ts-loader is used to load and parse TS files
      {
        test: /\.(ts|tsx)? $/.loader: 'ts-loader'.exclude: /node_modules/
      },
      // Used to load parse less files
      {
        test: /\.less$/.use: [{loader: 'style-loader'}, {loader: 'css-loader'.options: {
              modules: {
                localIdentName: '[hash:base64:6]',},}}, {loader: 'less-loader',},]},],},optimization: {
    minimize: true.// Enable code compression}};if (process.env.NODE_ENV === 'development') { tempConfig = { ... base,entry: path.join(__dirname, 'example/src/index.tsx'),
    output: {
      path: path.join(__dirname, 'example/dist'),
      filename: 'bundle.js'.library: 'laputarenderer'.libraryTarget: 'umd',},plugins: [
      // Automatically inject compiled packaged code into HTML
      new HtmlWebpackPlugin({
        template: path.join(__dirname, './example/src/index.html'),
        filename: 'index.html',})],devServer: {
      // Port: 8008, // Example boot port, optional}}; }module.exports = tempConfig;

Copy the code

Add script commands for development mode

Before adding commands, we need to specify the Node execution environment so that we can tell webPack whether it is a production or development environment and determine how it should be packaged. Install the following dependencies to set up the execution environment:

$ yarn add -D cross-env
Copy the code

Now we need to add some NPM execution commands to compile the example that runs the project.

// package.json
{
  // ...
  "scripts": {
    "start": "cross-env NODE_ENV=development webpack-dev-server --open"
  },
  // ...
}
Copy the code

Ok, so now that we’ve set up the development environment for this exercise renderer, let’s go aheadyarn startAfter compiling, the browser will automatically open example, 🉑️ and start doing whatever it wants

Once the development debugging is complete, we also need to compile and compress the renderer in production mode before the final release of the NPM package.

Set up production environment

Modify the WebPack configuration

Install a delete file dependency to automatically delete the last compiled and packaged files before each package.

#Used to clear /dist before compilation
$ yarn add -D clean-webpack-plugin
Copy the code

Modify the webpack. Config. Js

// webpack.config.js

// ...
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

// ...
if (process.env.NODE_ENV === 'development') {
  // ...
} else{ tempConfig = { ... base,entry: './src/index.ts'.output: {
      filename: 'index.js'.path: path.resolve(__dirname, 'dist'),
      library: 'laputarenderer'.library: 'umd'
    },
    devtool: 'none'.// When importing a module whose path matches one of the following, just
    // assume a corresponding global variable exists and use that instead.
    // This is important because it allows us to avoid bundling all of our
    // dependencies, which allows browsers to cache those libraries between builds.
    // We want to avoid putting all React files in one file, since it increases compile time and the browser can cache library files that have not changed.
    // Ideally, we would just introduce the React module in the browser, but most browsers don't support it yet.
    // Therefore most code bases wrap themselves in a single global variable, such as jQuery or _. This is called the "namespace" pattern,
    Webpack also allows us to continue using the code base written in this way.
    // With our "react": "react" setting, Webpack will magically convert all imports of "react" into loads from the React global variable
    
    // For details 🔎 see the reference document at the end of this article: React and Webpack
    externals: {
      'react': 'react'.'react-dom': 'react-dom'
    },
    plugins: [
      new CleanWebpackPlugin(),	Clear /dist before compiling]}; }module.exports = tempConfig;

Copy the code

Add production mode script command to execute compilation package 📦

Modify the package. The json

// package.json { // ... "scripts": { "build": "cross-env NODE_ENV=production npx webpack" }, // ... "PeerDependencies" : {" react ":" > = 16.9.0 ", "the react - dom" : "> = 16.9.0"}}Copy the code

⚠️ Note: Package. json adds the peerDependencies field, which tells other projects that want to install the library that they must install the dependencies I specified at the same level if they want to use my plug-in.

In this project, react and react-dom are specified. If another project A wants to install the renderer, it must install both react and React -dom.

Npm1 and NPM2 versions can install the renderer and automatically install the dependencies in peerDependencies, but later versions will need to install manually or you will receive a warning.

Read more about Peer Dependencies.

Since then, all preparations for the production model have been completed and executedyarn buildYou will then notice that the root directory of the project has been addeddistFolders, the last files to be published to NPM.

The next step is to start preparing for release to NPM ~

NPM ready for release

Modify package.json configuration

// package.json {"main": 'dist/index.js', // The file "types": "dist/index.d.ts", // specifies the file entry //... "Files ": ["dist"], // NPM release whitelist //... }Copy the code

The files field specifies that only the dist folder appears in the distributed package (readme. md and package.json are added by default).

NPM release

You must have an account at npmjs.com before Posting. If not, signup at www.npmjs.com/signup. If you have an account, run the NPM login command on the local terminal to login. The nPMjs.com account will automatically save the unique token of the current PC.

⚠️ Due to time constraints, automation has not been completed at present. You can add script commands to package.json, called NPM publish hooks, to do things like preversion, version, and postversion before publishing.

release

Make sure that the project is packaged and compiled in production mode before publishing, and that it is automated

$ npm publish
Copy the code

You can check out the new package on the nPMjs.com homepage at 🎉🎉🎉

An updated version

Updated version after modifying the project:

#Upgrade patch version 1.0.0 -> 1.0.1
$ npm version patch

#Upgrade version 1.0.0 -> 1.1.0
$ npm version minor

#Upgrade major version 1.0.0 -> 2.0.0
$ npm version major
Copy the code

Reference documentation

tsconfig.json

The React with webpack