preface

With the increase of web application complexity, componentization, engineering and automation have become the trend of front-end development. Each front-end team is building its own front-end development system, which is usually a piece-together, gradually running-in process, then how to achieve a complete set of front-end engineering program, the author hand in hand with everyone to achieve a.

The complete development process looks something like this

Webstorm is used to complete the project. Webstorm highly integrates many functions needed for the development of the project, including terminal, running script, git, Github login, Prettier save formatting, ESLint code check, etc. These functions are readily available without additional plug-ins. However, the IDE and editor is a matter of personal preference. If you don’t want to use Webstorm, you can simply ignore the Webstorm development tips presented in this article.

The project address

Making: github.com/shinewen189…

Static network address: shinewen189. Making. IO # / nigo – cli / /

Involved Technology stack

A complete front-end engineering architecture involves many technology stacks. In terms of technology selection, we should choose the technology stack according to our own project requirements. At least, we should see how hot the technology stack is and how its maintenance is. There is no blind pursuit of new, suitable for their own projects.

The technical stacks used in this project are listed below:

  • Build tool: Webpack5.x

  • Front-end framework: Vue 3.x

  • Routing tool: Vue Router 4.x

  • CSS precompilation: Less

  • Git Hook: Husky

  • Prettier + Eslint + Airbnb

  • Automatic deployment: Github Actions

Architectural structures,

Every great project starts with NPM init

npm init
Copy the code

NPM init, of course, you can also enter your project information.

Install the WebPack

cnpm i webpack webpack-cli webpack-dev-server -D
Copy the code
  1. -d is equivalent to –save-dev; Dependencies required when developing the environment
  2. -s is equivalent to –save; Required in the production environment

Distinguish between development and production environments

As our business logic grew, images, fonts, CSS, ES6, and CSS preprocessors were added to our projects, which led to an increase in configuration files that were cumbersome to write and even more serious (writing specific files in the wrong place). Configuration files are made worse by the different configurations of production and development environments in the project. Using a single configuration file affects the reusability of tasks, and as the requirements of the project grow, we must find ways to manage the configuration file more efficiently.

Add the build folder to the root directory, and then add the following files.

├ ─ build │ ├ ─ webpack.com mon. Config. Js// Public configuration,│ ├ ─ webpack. Dev. Config. Js//mode is the configuration for development│ ├ ─ webpack. Prod. Config. Js//mode is set to production│ ├ ─ webpack. Loader. Config. Js/ / configuration loader
Copy the code

If the configuration file is divided into many different parts, you must combine them in some way, usually by merging arrays and objects, and WebPack-Merge does this very well.

Take the webpack.dev.config.js file as an example. The webpack-merge of Webpack is used to merge the current file configuration into the common configuration.

const { merge } = require('webpack-merge')

const webpackConfigBase = require('./webpack.common.config')

module.exports = merge(webpackConfigBase(false), {
  mode: 'development'.devtool: 'eval-cheap-module-source-map'.module: {},
  plugins: [].devServer: {
    hot: true}})Copy the code

The installationdotenv,cross-envConfiguring environment Variables

cnpm i dotenv cross-env -D
Copy the code

Add two files in the root directory where you can add your own global variables, and then write different variables for different environments.

├ ─ env. Dev// Configure variables for the development environment├ ─ env. Prod// Configure the production environment variables
Copy the code

Modify the env. Dev

NODE_ENV = 'development'
VUE_SHOWCONSOLE = true  // Whether to display console
VUE_DEV_URL ='www.xxx.com' // Address of the development environment interface
Copy the code

Modify webpack.common.config.js to configure the written variables into the file

const { resolve } = require('path')
const webpack = require('webpack')


require('dotenv').config({ path: `.env.${process.env.envMode}` })
let env = {}
// Only NODE_ENV, BASE_URL and variables starting with VUE_APP_ will be statically embedded in client-side code via webpack.defineplugin
for (const key in process.env) {
  if (key === 'NODE_ENV' || key === 'BASE_URL' || /^VUE_APP_/.test(key)) {
    env[key] = JSON.stringify(process.env[key])
  }
}

module.exports = (mode) = > {
  return {
    .../
    plugins: [
      new webpack.DefinePlugin({
        // Define environment and variables
        'process.env': {
          ...env
        }
      })
    ]
  }
}
Copy the code

Two commands are added to the packgae.json file, respectively for the development environment and production environment

"scripts": {
  "dev": "cross-env envMode=dev webpack serve --config build/webpack.dev.config.js --color"."build": "cross-env envMode=prod webpack --config build/webpack.prod.config.js --color"
},
Copy the code

If there are other environments that can be added to suit your needs, such as test environments, pre-release environments, and so on

At this point we can try testing in different environments, starting with the development environment.

npm run dev
Copy the code

Run through the basic infrastructure to set up. The more in-depth configuration of webpack5 will be used below.

Add various technology stacks

With a Webpack-based architecture, we can continue to add the technology stack we need to use. What technology stack to add depends on the needs of our project. This paper takes vue3+VueRouter4+less as an example:

Install vue3 and VUE-Loader

cnpm i vue@next -D
cnpm i vue-loader@next @vue/compiler-sfc -D
Copy the code

Webpack. Loader. Config. Js add vue – loader

rules: [
    {
        test: /.vue$/,
        use: [
            'vue-loader']}]Copy the code

Webpack.com mon. Config. Add VueLoaderPlugin js

const { VueLoaderPlugin } = require('vue-loader/dist/index');
plugins: [
    new VueLoaderPlugin()
]
Copy the code

Transfer ES6 + ES5

Because some browsers cannot parse advanced syntax such as ES6+, you need to convert it to a lower-level syntax that the browser can parse

cnpm i @babel/core @babel/preset-env babel-loader -D
Copy the code

Babel – loader configuration

// webpack.loader.config.js
rules: [{test: /.js$/,
        exclude: /node_modules/,
        use: {
            loader: 'babel-loader',}},]Copy the code

Babel configuration file

Add babel.config.js to the root directory

// babel.config.js

module.exports = {
  presets: [['@babel/preset-env',
      {
        targets: {
          browsers: ['last 2 versions'] // Last 2 browser versions}}]]}Copy the code

HTML – webpack – the plugin installation

Install htML-webpack-plugin to process index. HTML file. The function of this plugin is to automatically generate the correct project entry file according to the template file provided, and automatically insert the JS file packed by Webpack into it

cnpm i html-webpack-plugin -D
Copy the code

Plugins configuration

// webpack.common.config.js
new HtmlWebpackPlugin({
	template: resolve(__dirname, '.. /index.html'),
	filename: 'index.html'.title: 'nigo-cli'.minify: {
		html5: true.// Parse the input according to the HTML5 specification
		collapseWhitespace: true.// Fold blank area
		preserveLineBreaks: false.minifyCSS: true.// Compress the CSS in the text
		minifyJS: true.// Compress the text js
		removeComments: false // Remove comments}})Copy the code

Add the vue – the router

cnpm i vueRouter@last -D
Copy the code
├ ─ SRC ├ ─ the router │ ├ ─ index, js// Define routing rules
Copy the code

Example Modify the route index.js routing rule

import { createRouter, createWebHashHistory } from 'vue-router'

const routes = [
  {
    path: '/'.name: 'home'.component: () = > import('@/view/home.vue')}]const router = createRouter({
  history: createWebHashHistory(),
  routes 
})

export default router
Copy the code

Mount the routing configuration in the main.js file

import { createApp } from 'vue'
import App from '@/App.vue' // Introduce the APP page structure
import router from '@/router'

createApp(App).use(router).mount('#app')
Copy the code

Add less preprocessors

cnpm i style-loader css-loader less-loader -D
Copy the code

Webpack. Loader. Config. Js add less – loader

rules: [
{
  test: /.less$/,
  use: ['style-loader'.'css-loader'.'less-loader']]},Copy the code

In this way, the architecture integrated with Vue3+VueRouter4+ Less is basically set up. In the future, we can also add Vuex state management tool, Axios and other CSS preprocessors.

Configuration webpack

Configuring alias Alias

Configure @ to alias the/SRC directory that places resources and source code in the project root directory. Follow your own requirements, such as adding static resource aliases

Add the following code to webpack.common.config.js

/ /...
resolve: {
/ /...
alias: {
 The '@': resolve('src')}}Copy the code

Processing static resources such as images

Before Webpack5, we used url-loader, file-loader, and raw-loader to process static resources such as PNG images and SVG ICONS. Webpack5 provides built-in static resource building capabilities. We do not need to install additional loaders, and only need simple configuration to realize the packaging and directory storage of static resources. All three loaders have also stopped updating on Github.

Webpackage 5 replaces these loader functions with four new Asset Modules.

Asset /resource Splits the resource into separate files and exports the URL, which is what file-loader used to do. Asset /source exports resources as source code. Asset automatically selects export as a separate file or dataURL (default: 8KB). Previously, urL-loader set asset Size limit to restrict implementation.

Configuration webpack. Loader. Config. Js

{
    test: /.(png|jpg|svg|gif)$/,
    type: 'asset/resource'.generator: {
        // [ext] comes with a "."
        filename: 'assets/[hash:8].[name][ext]',}}Copy the code

Clear the dist directory

Clean-webpack-plugin is generally used to clear dist file contents in webPack5.20 or later. After 5.20, clean is added to output to clear dist directory

Configuration webpack. Prod. Config. Js

module.exports = {
  / /...
  output: {
    clean: true.// Clean the output directory before emit.}};Copy the code

FileSystem Cache accelerates secondary builds

Before Webpack5, we used cache-loader to cache some loaders with high performance overhead, or used hard-source-webpack-plugin to provide some intermediate cache for modules. After Webpack5, a built-in caching capability (caching modules and chunks) was integrated for us by default. You can speed up the secondary build by doing the following.

Configuration webpack. Prod. Config. Js

module.exports = {
    / /...
    cache: {
        type: 'filesystem'.// Optional
        buildDependencies: {
            config: [__filename],  // The cache is invalidated when the contents of the config file that builds the dependency (via the require dependency) change
        },
        name: ' '.// Create different cache files with name as isolation. For example, generate different configuration cache for PC or mobile
        / /...}},Copy the code

The above describes only the new webpack5 features and basic configurations. You will need to configure them as required. Including CSS separation, CSS compression, JS compression, and so on, here is not a discussion.

Code specification

The above architecture is generally set up to meet individual development needs because there is no need to worry about teamwork, code specifications, submission specifications, and so on.

But if it’s a team effort, we need to consider the code specification. Due to the flexibility of JavaScript, there are often multiple ways to write a piece of code, which can also lead to collaborative differences. Also, there are some scripts that can lead to bugs that aren’t easy to find, or that don’t perform well and should be avoided during development.

To solve this type of static code problem, each team needs a common JavaScript code specification that team members follow to write code. Of course, relying on people to guarantee code specifications is not reliable, and a corresponding tool is needed to guarantee them.

Install the Prettier

Prettier Prettier is a powerful code formatting tool that supports JavaScript, TypeScript, CSS, SCSS, Less, JSX, Angular, Vue, GraphQL, JSON, Markdown, etc. Basically the front end can use the file format it can be done, is the most popular code formatting tool.

cnpm i prettier -D
Copy the code

Create the.prettierrc file in the project root directory where you can configure a unified formatting style for the team.

{
  "useTabs": false."tabWidth": 2."printWidth": 100."singleQuote": true."trailingComma": "none"."bracketSpacing": true."semi": false
}
Copy the code

If you want to save the file and format it later, go to “File wathcer” in Webstorm Settings, add “prettierrc”

Click the Settings below, then save the modified file will automatically follow.prettierrcConfiguration to format, cool don’t don’t.The file will be reformatted as soon as you save it

Install ESLint

cnpm i eslint -D
Copy the code

After ESLint is installed successfully, execute NPX ESLint –init and follow terminal instructions to complete a series of Settings to create the configuration file.

If automatic installation fails, manual installation is required

cnpm i eslint-config-airbnb-base -D 
cnpm i eslint-plugin-vue -D
cnpm i eslint-config-prettier -D
cnpm i eslint-import-resolver-webpack -D
cnpm i eslint-plugin-import -D
cnpm i eslint-plugin-prettier -D
cnpm i eslint-webpack-plugin -D
Copy the code

Add the ignore check file in the root directory. Eslintignore

node_modules
dist/
build/
/*.js
Copy the code

Add.eslintrc.js to the root directory

module.exports = {
  root: true.// This is used to tell ESLint that the current configuration file cannot be looked up by its parent
  env: {
    browser: true.es2021: true
  },
  extends: ['plugin:vue/essential'.'airbnb-base'.'plugin:prettier/recommended'].parserOptions: {
    parser: 'babel-eslint'.ecmaVersion: 2018.sourceType: 'module'
  },
  plugins: ['vue'.'prettier'].settings: {
    'import/resolver': {
      webpack: {
        config: 'build/webpack.dev.config.js'}}},rules: {
    'prettier/prettier': 'error'}}Copy the code

After Webpack5.20, eslint-loader is not required to directly add the following code to webpack.common.config.js

plugins:[
new ESLintPlugin({
  // fix: true,
  extensions: ['js'.'json'.'vue'].exclude: '/node_modules/'})]Copy the code

If you want to wave code in red in WebStorm, you can go to EsLint in Settings and use the Settings shown below

Open any JS file or vue file and see that the variable is not marked in red

Terminals also report variables that are not used.

In this project, we will use Airbnb’s code specification. Of course, you can use other team specifications or customize some team rules. Rules defined by ESLint will not be discussed here

Commit git repository

Create a commit ignore file in the root directory. Gitignore

logs/
npm-debug.log
yarn-error.log
node_modules/
dist/
package-lock.json
yarn.lock
.idea/
Copy the code

Log on to GitHub at Webstorm

Open webStorm Settings, search Github, you can choose account password login or token (token needs to be created on Github)

After login, click Test in the upper right corner, and the connection will be successful.

SSH keys are generated locally and added to GitHub

Because transport between our local Git repository and GitHub repository is encrypted over SSH, we need to configure authentication information

Git command line generates the secret key

ssh-keygen -t rsa -C "[email protected]"
Copy the code

The email account here is your GitHub email account (after hitting Enter, you may be asked to enter your account and password), but just press enter. The secret key is generated on success. Open the id_rsa.pub file on your hard drive (search for it yourself) and copy the key inside

Click Setting => SSH and GPG keys, then add SSH

After adding git, you can enter the following command to verify the success

ssh -T [email protected]
Copy the code

If a message is displayed when you run the command for the first time, enter yes. The following information indicates that the verification succeeds

Hi yourname! You've successfully authenticated, but GitHub does not provide shell access.
Copy the code

Upload the project to GitHub

Click on the head VCS in Webstorm

Click Share Project on GitHub and fill in the repository name and so on.

Open the Github repository

There are several ways to submit a Github repository, such as the command line, creating a repository on a website, and so on. This can be done according to personal preference.

Submit specifications

We already integrate ESLint and Prettier into the project, where they verify code in real time and, to a certain extent, regulate it, but some people on the team may find the restrictions cumbersome and choose to ignore “hints”. Write your code in your own style, or disable the tools altogether, and commit your code directly to the repository. Over time, ESLint becomes useless.

So, we also need to make certain that the repository code is spec compliant by making it impossible to commit code that has not passed ESLint detection and fixes.

To solve this problem, you need to use a Git Hook. When a local Git commit is performed, ESLint checks and fixes the committed code (i.e., ESLint –fix). If the code fails to pass the ESLint rule, the commit is disabled.

To do this, we use Husky

Husky — Git Hook, which can be set to trigger Git commands at various stages (pre-commit, commit-msg, pre-push, etc.).

Use the husky-init command to quickly initialize a husky configuration in your project.

npx husky-init && cnpm install
Copy the code

The command generates a. Husky folder and some files

Modify the pre – commit

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm run lint
Copy the code

Package. Jon adds the command

"scripts": {
  "lint": "eslint --ext .js,.vue src"
},
Copy the code

Test the submission code and see that the code with an error cannot be submitted.

There may be a lot of problems at the beginning of using ESint, and it takes a lot of time and effort to change. As long as you stick to it, the code quality and development efficiency will be improved, and the initial effort is worth it.

Automatic deployment project

Create a lot Token

Create a GitHub Token with repo and Workflow permissions

Note: Newly generated tokens are displayed only once and saved for later use. If it is lost, it can be regenerated.

Add Secret to the repository

Add the new Token to GitHub repository Secrets and name the new secret NIGO_DEV (whatever you like).

Steps: Repository -> Settings -> Secrets -> New Repository Secret.

Create the Actions configuration file

  1. Create in the project root directory.githubDirectory.
  2. in.githubDirectory creationworkflowsDirectory.
  3. inworkflowsDirectory creationdeploy.ymlFile.

Modify the deploy.yml file and add the following code


name: deploy

on: Push: Branches: [master] # Master triggered when there is a pushjobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Setup Node.js v14.x
        uses: actions/setup-node@v1
        with:
          node-version: '14.x'

      - name: Install
        run: yarn install # Install dependency - name: Buildrun: NPM run build # package-name: Deployuses: Peaceiris /actions-gh-pages@v3 # Use the actions deployed to GitHub Pageswith: publish_dir:./dist # Deploys the packaged dist directorygithub_token${{secretsecrets.NIGO_DEV}} # secretuser_name: ${{ secrets.MY_USER_NAME }}
          user_email: ${{ secrets.MY_USER_EMAIL }}
          commit_messageGit commit information for deployment: Update #Copy the code

Github Actions will then automatically deploy as soon as the code changes are submitted

The code deployed here goes to the GH-Pages branch, which is created automatically

Making warehouse – > Settings – > pages read gh – branch of pages, and then access shinewen189. Making. IO/nigo – cli /

Automatic deployment is only a small part of GitHub Actions. There are many more things you can do with GitHub Actions.

The last

A complete front-end engineering architecture solution requires consideration of technology selection, differentiated environments, code specifications, submission specifications, testing, automated deployment, and so on. This project only provides basic configuration for each technology stack. Students can study or configure each technology stack according to their own needs to find the most suitable engineering scheme.

Finally, attach the project address

Making: github.com/shinewen189…

Static network address: shinewen189. Making. IO # / nigo – cli / /