Build Vue development environment from zero: webPack4 + vue-loader + KOA2 + babel-loader V8 + Babel v7 + esLint + Git hooks + EditorConfig

From 2009 to 2019 society has moved on and technology has moved on and we certainly can’t be left behind

“A thousand miles without accumulation, not small streams without rivers and oceans”

Start with the basic WebPack build

Create a project directory vue-structure

mkdir vue-structure && cd vue-structure
Copy the code

Install webpack

npm i webpack webpack-cli -D
Copy the code

Create build directory

mkdir build
Copy the code

In the build directory, create webpack.config.js

cd build && touch webpack.config.js
Copy the code

Create the entry file SRC /main.js

mkdir src

cd src && touch main.js
Copy the code

main.js

alert('hello world! ')
Copy the code

Configuration of NPM scripts

  // package.json 
  "scripts": {
    "build": "webpack --config build/webpack.config.js --progress --mode production"
  }
Copy the code

Configuration devServer

npm i webpack-dev-server -D
Copy the code

Configuration of NPM scripts

  "scripts": {..."dev": "webpack-dev-server --config build/webpack.config.js --progress --mode development"
  }
Copy the code

HTML plugin

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

Webpack configuration

// build/webpack.config.js

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

const resolve = dir => path.join(__dirname, '.. ', dir)

module.exports = {
  entry: resolve('src/main.js'),
  output: {
    filename: '[name].[hash:5].js',
    path: resolve('dist')
  },
  devServer: {
    host: '0.0.0.0',
    port: 7000,
    open: true
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: resolve('index.html')]}})Copy the code

Run WebPack Dev Server

npm run dev
Copy the code

The browser automatically opens http://0.0.0.0:7000/

At this point, the Webpack development service is basically running

Configure the Babel v7

webpack 4.x | babel-loader 8.x | babel 7.x

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

Babel Plugin supports dynamic import()

npm i @babel/plugin-syntax-dynamic-import -D
Copy the code

Configuration webpack. Config. Js

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

Create the.babelrc file

{
  "plugins": [
    "@babel/plugin-syntax-dynamic-import"]."presets": [["@babel/preset-env",
      {
        "modules": false}}]]Copy the code

Test the ES6 code

test.js

  // src/test.js
  export default () => alert('hello vue! ')
Copy the code

index.html

  // src/index.html
  <body>
    <div id="app">请说say</div>
  </body>
Copy the code

main.js

 // src/main.js
 document.querySelector('#app').addEventListener('click', () => {
  import('./test.js').then(res => {
    res.default()
  })
})
Copy the code

Run dev

npm run dev
Copy the code

Click on the page div

Ok, no problem

Configure the Vue Loader

What is a Vue Loader?

Vue Loader is a Webpack Loader that allows you to write Vue components in a single file component (*.vue file) format:

Create the app. vue root component

<template>
  <div class="example">{{ msg }}</div>
</template>

<script>
export default {
  data () {
    return {
      msg: 'Hello Vue! '
    }
  }
}
</script>

<style>
.example {
  color: red;
}
</style>

Copy the code

Install the Vue

npm i vue
Copy the code

src/main.js

import Vue from 'vue'
import App from './App.vue'

new Vue({
  render: h => h(App)
}).$mount('#app')
Copy the code

Modified index. HTML

<body>
  <div id="app"></div>
</body>
Copy the code

Run the dev

npm run dev
Copy the code

By default, webpack only recognizes JavaScript files and cannot parse. Vue files (vue single file components are unique to Vue), so the author provides vue-loader.

Vue single file component

Cn.vuejs.org/v2/guide/si…

Configure the vue – loader

npm i vue-loader vue-template-compiler
Copy the code

Vue-template-compiler (peer Dependency) is a version-dependent of vue-Loader

webpack.config.js

// webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin'Module. Exports = {module: {rules: [//...test: /\.vue$/,
        loader: 'vue-loader'}]}, plugins: [// please make sure to introduce this plugin! New VueLoaderPlugin()]}Copy the code

The CSS in vUE single-file components also needs CSS-Loader to parse

npm i css-loader -D
Copy the code

Configuration webpack

// webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'}, / / it will be applied to the common ` js ` file / / and ` vue ` file ` < script > {` blocktest: /\.js$/,
        loader: 'babel-loader'}, / / it will be applied to the common ` CSS ` file / / and ` vue ` file ` < style > {` blocktest: /\.css$/,
        use: [
          'vue-style-loader'.'css-loader'[// please make sure to introduce this plugin to cast magic new VueLoaderPlugin()]}Copy the code

NPM run dev OK, app. vue is successfully mounted to the page

CSS preprocessor configuration

npm i stylus stylus-loader
Copy the code

webpack.config.js

module: {
    rules: [
      {
        test: /\.styl(us)? $/, use: ['vue-style-loader'.'css-loader'.'stylus-loader']]}}Copy the code

Used in vUE components

<style lang='stylus' scoped>
.example
  .title
    color: red
</style>
Copy the code

Postcss configuration

Postcss provides a parser that parses CSS into abstract syntax trees (AST).

npm i -D postcss-loader
Copy the code

Autoprefixer parses CSS files and adds browser prefixes to CSS content

npm i -D autoprefixer
Copy the code

Create postcss. Config. Js

module.exports = {
  plugins: [
    require('autoprefixer')]}Copy the code

Configuration webpack

// webpack.config.js
  module: {
    rules: [
      ...
      {
        test: /\.css$/,
        use: [
          devMode ? 'vue-style-loader' : MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              sourceMap: true
            }
          },
          {
            loader: 'postcss-loader',
            options: {
              sourceMap: true}}]}, {test: /\.styl(us)? $/, use: [ devMode ?'vue-style-loader' : MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              sourceMap: true
            }
          },
          {
            loader: 'postcss-loader',
            options: {
              sourceMap: true
            }
          },
          {
            loader: 'stylus-loader',
            options: {
              sourceMap: true}}]}Copy the code

Add cSS3 styling to app.vue

At this point, NPM run dev can see that the browser prefix is automatically added

Image resource loading configuration

url-loader

Convert the image resource to a Base64 URI

// webpack.config.js

module: {
  rules: [
    {
      test: /\.(png|svg|jpe? g)$/, loader:'url-loader',
      options: {
        limit: 8192}}]}Copy the code

The image address is changed to a Base64 URI

file-loader

Loading icon fonts

module: {
  rules: [
    {
      test: /\.(woff|woff2|eot|ttf|otf)$/,
      use: ['file-loader']]}}Copy the code

cross-env

Set the environment variables for the command run time to differentiate the environment in the WebPack configuration file

npm i cross-env -D
Copy the code

package.json

  "scripts": {
    "build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js --progress --mode production"."dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.js --progress --mode development"
  },
Copy the code

CSS extract

webpack4

npm i mini-css-extract-plugin -D
Copy the code

webpack.config.js

Const devMode = process.env.node_env ==='development'

module: {
  rules: [
    {
      test: /\.css$/,
      use: [
        devMode ? 'vue-style-loader' : MiniCssExtractPlugin.loader,
        'css-loader'] {},test: /\.styl(us)? $/, use: [ devMode ?'vue-style-loader' : MiniCssExtractPlugin.loader,
        'css-loader'.'stylus-loader'
      ]
    }
  ]
},

plugins: [
  ...
  new MiniCssExtractPlugin({
    filename: '[name].css',
    chunkFilename: '[id].css'})]Copy the code

Generally, CSS extraction is not enabled in the development environment. Otherwise, the recompilation of each code change will be slow. CSS extraction is usually turned on during packaging in a build environment.

At this point NPM run build, CSS is packaged separately into a CSS file

Clearing the dist directory

Why would you want to clean up the dist directory in production because our output file is going to be a hash for cache and we’re going to concatenate the file name, and whenever we change the file name it’s going to generate a new hash, and we’re going to add a new output file every time in dist but we’re just going to compile the final one, right

NPM run build three times dist directory is as follows

Dist ├ ─ ─ app. Bundle. 0 e380cea371d050137cd. Js ├ ─ ─ app. Bundle. 259 c34c1603489ef3572. Js ├ ─ ─ App. Bundle. E56abf8d6e5742c78c4b. Js ├ ─ ─ index. The HTML └ ─ ─ style. The CSSCopy the code
module.exports = {
    output: {
    filename: '[name].[hash:6].js',
    path: resolve('dist')}},Copy the code

Use the WebPack plug-in to clean up

clean-webpack-plugin

npm i clean-webpack-plugin -D
Copy the code

Webpack configuration

// build/webpack.config.js

const CleanWebpackPlugin = require('clean-webpack-plugin')

module.exports = {
  plugins: [
    new CleanWebpackPlugin(['dist'], {
      root: path.join(__dirname, '.. / ')]}})Copy the code

Then running NPM Run build cleans up the dist directory before each package

The second way is to clean up the dist directory with rimraf

rimraf

The UNIX command rm -rf for node.

npm i rimraf -D
Copy the code

Modify the package. The json

"scripts": {
    "clean": "rimraf dist"."build": "npm run clean && cross-env NODE_ENV=production webpack --config build/webpack.config.js --progress --mode production",}Copy the code

NPM run build is also OK

.editorconfig

Maintain a consistent coding style for multiple developers working on the same project in different editors and IDEs.

root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
Copy the code

editorconfig.org/

Code verification (Linting)

Install eslint

 npm i eslint eslint-plugin-vue -D
Copy the code

Eslint various installations

npm i -D babel-eslint eslint-config-standard eslint-plugin-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-node
Copy the code

Create the.eslintrc file

{
  root: true,
  env: {
    node: true
  },
  parserOptions: {
    parser: "babel-eslint".sourceMap: "module"
  },
  extends: [
    "plugin:vue/essential"."standard"
  ],
  rules: {}
}
Copy the code

Configure ESLint in WebPack

Through webpack real-time compilation, code validation

npm i eslint-loader -D
Copy the code

webpack.config.js

module: {
  rules: [
    {
      {
        enforce: 'pre'.test: /\.(js|vue)$/,
        loader: 'eslint-loader', exclude: /node_modules/ }, ...... }}]Copy the code

Define an unused variable in SRC /main.js

let title = 'eslint'
Copy the code

Run NPM run dev

Eslint is basically configured but I thought it would be nicer to report error messages on the console

eslint-friendly-formatter

A simple ESLint formatting tool/reporter that uses advanced text and iterm2 “click to open file” functionality friendly

The installation

npm i -D eslint-friendly-formatter
Copy the code

Modify the WebPack configuration

// build/webpack.config.js

module: {
  rules: [
    {
      {
        enforce: 'pre'.test: /\.(js|vue)$/,
        loader: 'eslint-loader',
        exclude: /node_modules/,
        options: {
          formatter: require('eslint-friendly-formatter')}},... }}]Copy the code

NPM run dev again

In this case, error messages are displayed on the cli

devServer.overlay

Display compilation errors directly to the browser page.

webpack.config.js

module.exports = {
  devServer: {
    overlay: {
      errors: true,
      warnings: true}}}Copy the code

NPM run dev again so you can see the error message directly on the page

Configure ESLint in package.json

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

A separate validation code through NPM is also possible

npm run lint
Copy the code

Eslint automatically fixes

How can problems detected by Eslint be fixed automatically

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

It will automatically fix some common errors in your code

Git Hooks

Git can trigger custom scripts when certain important actions occur. Similar to the lifecycle in the framework

Git-scm.com/book/zh/v2/…

husky

npm install husky --save-dev
Copy the code

www.npmjs.com/package/hus…

Create huskyrc.

// .huskyrc
{
  "hooks": {
    "pre-commit": "npm run lint"}}Copy the code

package.json

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

NPM run Lint is automatically executed every time git commit

Webpack code separation

Code separation is performance optimization (business code third party code Webpack runtime code generation…)

You can configure it directly in webpack4

// build/webpack.config.js module.exports = {optimization: {splitChunks: {// Default to bundle dependencies in node_modules into venders.js chunks:'all'}, // package the WebPack runtime generation code into runtime.js runtimeChunk:true}},Copy the code

NPM run build now sees vendors. Js and Runtime.js

See the official documentation for more configuration of the optimization option in webpack4

Webpack.js.org/configurati…

Complete configuration file at present

package.json

  "scripts": {
    "clean": "rimraf dist"."build": "npm run clean && cross-env NODE_ENV=production webpack --config build/webpack.config.js --progress --mode production"."dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.js --progress --mode development"."lint": "eslint --ext .js,.vue src"."lint:fix": "eslint --fix --ext .js,.vue src"
  },
Copy the code

build/webpack.config.js

const path = require('path')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CleanWebpackPlugin = require('clean-webpack-plugin')

const resolve = dir => path.join(__dirname, '.. ', dir)

const devMode = process.env.NODE_ENV === 'development'

module.exports = {
  entry: resolve('src/main.js'),
  output: {
    filename: '[name].[hash:6].js',
    path: resolve('dist')
  },
  module: {
    rules: [
      {
        enforce: 'pre'.test: /\.(js|vue)$/,
        loader: 'eslint-loader',
        exclude: /node_modules/,
        options: {
          formatter: require('eslint-friendly-formatter')}}, {test: /\.vue$/,
        use: 'vue-loader',
        exclude: /node_modules/
      },
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: [
          devMode ? 'vue-style-loader' : MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              sourceMap: true
            }
          },
          {
            loader: 'postcss-loader',
            options: {
              sourceMap: true}}]}, {test: /\.styl(us)? $/, use: [ devMode ?'vue-style-loader' : MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              sourceMap: true
            }
          },
          {
            loader: 'postcss-loader',
            options: {
              sourceMap: true
            }
          },
          {
            loader: 'stylus-loader',
            options: {
              sourceMap: true}}]}, {test: /\.(png|svg|jpe? g)$/, loader:'url-loader',
        options: {
          limit: 8192}}, {test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: ['file-loader'}}, optimization: {splitChunks: {// by default, node_modules dependencies are packaged into venders.js chunks:'all'}, // Package the WebPack runtime code into runtime.js runtimeChunk:true
  },
  devServer: {
    host: '0.0.0.0',
    port: 7000,
    open: true,
    overlay: {
      warnings: true,
      errors: true
    }
  },
  plugins: [
    new VueLoaderPlugin(),
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css'
    }),
    new HtmlWebpackPlugin({
      template: resolve('index.html')
    })
    // new CleanWebpackPlugin(['dist'], {
    //   root: path.join(__dirname, '.. / ') //})]}Copy the code

Webpack configuration source code address

Github.com/Lwenli1224/…

When it comes to the night is the heart of the most quiet time without distractions.