Lengthy preface

This tutorial will complete a page: to view the year’s progress, click here. The page is simple. Write a small tutorial, one is learning summary, output, to teach for learning; The second is to help new people learn. If there are any deficiencies or omissions, please point them out and I will correct them in time to avoid mistakes.

Thread the outline

This tutorial will start from the simplest new HTML page, with the most original HTML, CSS, JS to achieve the page, and then on the basis of page implementation, use ES7 class to achieve the same effect, and then, began to use node environment, NPM package management, front-end engineering with Webpack, Let the resulting code: JS converted to ES5, CSS code added vendor prefix

  • 1. Single page HTML to achieve this year’s schedule display
  • 2. Split page files (JS, CSS separation) and adopt new syntax above ES6
  • 3. Webpack front-end engineering

Front knowledge

This tutorial is for beginners, but still need to have a little pre-knowledge: JS, CSS, Git repository management and NPM package management, even if part of the understanding, it doesn’t matter, through the tutorial is also a little understanding. Git knowledge is needed here because I’ve split each stage of the tutorial into a branch so readers can dig into the details

Edible Suggestions

The tutorial code has been pushed to a remote repository. Each section has a branch, and each section has a commit. You can switch to the corresponding branch as you read through the tutorial, or you can use tools to see the changes between the two Commits if you want

Blind guess the git command readers will use

git clone https://github.com/guojianglin/tiny_tutorial.git git pull -a git branch git checkout 1. Git Checkout 2 is a one-page HTML implementation. Git checkout 3. Create git log --oneline for webpack front-endCopy the code

1. Single file HTML page to achieve this year’s schedule display

1.1 Project Creation

Create a new folder namedtiny_tutorialwithvscodeOpen,tiny_tutorialDirectory creates a fileindex.htmlIn theindex.htmlThe input!And press enter,vscodeAn empty HTML template is automatically generated, as shown below:

1.2 HTML framework and style implementation

This part is mainly the implementation of static style, without too much explanation. If you don’t understand the style, you can Google or Baidu. I used a background image hereHTML skeleton

  <div class="page-container">
    <div class="refresh-btn">refresh</div>

    <div class="message-wraper">
        <div class="title">Your <span class="year">2099</span> Progress</div>

        <div  class="message">
            <span class="year">2099</span>Has been slipping away<span class="days-has-past">1</span>Oh, my God, it's over<span class="percent"></span>%
        </div>

        <div class="progress-container"></div>
    </div>
  </div>
Copy the code

CSS styles

    body.html {
      margin: 0;
      padding: 0;
      color: rosybrown;
      height: 100%;
    }
    .page-container {
      height: calc(100vh);
      display: flex;
      align-items: center;
      justify-content: center;
      background-image: url('./Chihiro.jpg');
      background-repeat: repeat;
      background-size: contain;
      background-position: center;
      flex-direction: column;
    }
    .page-container .refresh-btn {
      height: 50px;
      line-height: 50px;
      padding: 0 20px;
      color: # 333;
      font-size: 20px;
      font-weight: 900;
      background-color: greenyellow;
      border-radius: 5px;
      margin-bottom: 20px;
      box-shadow: lightblue 2px 4px 10px;
    }
    .refresh-btn:hover {
      cursor: pointer;
      background-color: rgb(91.201.238);
      color: white;
    }
    .message-wraper {
      display: flex;
      align-items: center;
      justify-content: center;
      flex-direction: column;
      background-color: rgba(0.0.0.5);
      width: 80%;
      margin: 0 30px;
      padding: 20px;
    }
    .message-wraper .title {
      text-align: center;
      font-size: 6vw;
      padding: 10px;
      margin-bottom: 30px;
      font-weight: bolder;
      color: whitesmoke;
    }
    .message-wraper .message {
      margin-bottom: 20px;
    }
    .message .year {
      font-weight: bold;
    }
    .message .days-has-past..message .percent {
      font-weight: bold;
      color: greenyellow;
    }
    .message .days-has-past {
      opacity: 1;
      font-size: 80px;
    }
    .message .percent {
      opacity: 1;
      font-size: 21px;
    }
    .message-wraper .progress-container {
      border-radius: 15px;
      width: 60%;
      height: 27px;
      background-color: pink;
      display: flex;
      justify-content: stretch;
      overflow-x: hidden;
    }
    .progress-container .finish {
      background-image: linear-gradient(45deg.#f3f730 25%.# 000000 0.# 000000 50%.#f3f730 0.#f3f730 75%.# 000000 0);
      background-size:15px 15px;
      width: 0%;
      transition: all 3s ease-in;
    }
Copy the code

Here’s what the page looks like

1.3 PAGE interaction JS implementation

The end result: the page loads and calculates how much of the year has gone by, expressed as a progress bar and percentage, and the progress bar and percentage need to have an increasing “animation effect” that can be recalculated and animated by hitting the refresh button. The calculations involved are a little bit tedious, but they’re not difficult, and I don’t want to explain them too much here because I don’t have space,Click here to experience the interaction

2. Split page files (JS, CSS separation) and adopt new syntax above ES6

2.1 Page File Splitting (JS, CSS separation)

This step is fairly simple, just separate the CSS and JS sections into separate folders and link them to the HTML page

2.2 Adopt the new syntax features above ES6

This part isn’t that hard, it’s almost like moving the methods and variables inside the class, using arrow functions, and noticethisPointing to. (This part of the operation is mainly to prepare for the later webpack packaging and compilation into ES5)

3. Webpack front-end engineering (install node environment by Google or Baidu)

3.1 NPM initializes and adds. Gitignore

Execute: NPM init-y under the project root, which will add a package.json file under the project

Add. Gitignore file and write to itnode_modules distThe two folders that are written to git are ignored and not committed to the git repository, even though they don’t exist yet

3.2 Preparation for Webpack front-end engineering

First, we need to install the WebPack dependency, where WebPack is the core code package and WebPack-CLI is the command line tool

npm install webpack webpack-cli --save-dev
// or
cnpm install webpack webpack-cli --save-dev
Copy the code

Next, create a new WebPack configuration file, webpack.config.js, under the project root. This is the simplest configuration for WebPack, with the entry file and output location configured

const path = require('path');

module.exports = {
  mode: 'none'.entry: './index.js'.output: {
    filename: 'main.js'.path: path.resolve(__dirname, 'dist'),}};Copy the code

Next, we add a command to scripts in the package.json file. After adding this command, NPM run build(equivalent to NPX webpack –config./webpack.config.js) There is a main.js file inside

 "scripts": {
    "build": "webpack --config ./webpack.config.js"
  },
Copy the code

Pack it outmain.jsFiles, introduced in HTML, can also be found to achieve interactive effects. This is where the problem arises: it doesn’t seem to be doing much good just to process js files. That’s because we’ve only configured the simplest packaging,moduleandpluginsConfiguration is the soul that makes WebPack come alive

In the past, our JS files, the files that we introduced, were just JS files, and if we introduced CSS files or images, we would definitely get an error when we executed, and we have thatwebpackAfter that, you can import other types of files directly into JS, and then configure loader to parse different files, and finally package executable files

3.3 WebPack Configuration Practices

This section of the configuration, I refer to the nuggets author Miyazoghaku’s article Webpack – from the basic use to manual implementation of configuration, he has some configuration to understand said, so the following steps I will not explain in detail, if you have questions, you can skip to query the corresponding part of the article; Of course, you can also refer to this nuggets article – “once and for all” from shallow to deep configuration webpack4

  • Requirement: I want to be able to package, generate an HTML file from the original index. HTML, import and package other files, such as JS, CSS and so on. (Now I have to manually import the packaged stuff myself to see how it works.)
// Install dependencies first
npm i html-webpack-plugin -D
// or
cnpm i html-webpack-plugin -D
Copy the code

Do this in webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin')...module.exports = {  
  ...
  plugins: [
    new HtmlWebpackPlugin({
      template: './index.html'.// Template file address
      filename: 'index.html'.// Specify the name of the packaged file})]};Copy the code

Then perform a packagenpm run buildAs shown in the figure, we can see that there are more files in the dist directoryindex.htmlSo the originalindex.htmlIt’s superfluousindex.jsIt should be removed and packaged again

At this point, when we open the generated index.html in the browser, we find that there are no styles, no background images, just HTML and interactive effects, as shown in the figure below

So, our next goal is clear, packaging needs to have style

  • Requirement: Wrap styles in
NPM I CSs-loader style-loader -d // or CNPM I CSs-loader style-loader -dCopy the code

Do this in webpack.config.js

module.exports = {
  ...
  module: {
    rules: [{test: /\.css$/,
        use: ['style-loader'.'css-loader']},]}};Copy the code

Add (fancy!) at the top of the index.js file. CSS was introduced in HTML, now it is introduced in JS) :

import './style.css'
Copy the code

And then put the originalindex.htmlthe<link rel="stylesheet" href="./style.css">Introduce CSS remove; In addition, we have not configured the packaging picture, so there will be error packaging at this time, let’s firststyle.cssInside quote background picture comment out

performnpm run buildPack it up, open it again in the browser, and it looks as expected: except for the background image we commented out, all the styles appear normally, so we have no problem with the configuration of the styles

At this point, I don’t want the CSS styles to end up in the HTML, but rather in a separate file to avoid having too many styles and inserting too many styles into the HTML

// install NPM I mini-css-extract-plugin-d or CNPM I mini-css-extract-plugin-dCopy the code

Do this in webpack.config.js

const MinniCssExtractPlugin = require('mini-css-extract-plugin')...module.exports = {
  ...
  plugins: [...new MinniCssExtractPlugin({
      // Specify the name of the output file
      filename: 'main.css'})].module: {
    rules: [{test: /\.css$/,
        use: [ MinniCssExtractPlugin.loader,'css-loader'] // Replace style-loader}]}};Copy the code

After executing the NPM run build again, you can see that there is now a main. CSS file under the dist directory, which is also introduced in the index.html file under the same directory

  • Requirement: Add vendor prefixes to packaged CSS styles for browser compatibility
NPM I postcss-loader autoprefixer -d // or CNPM I postcss-loader autoprefixer -dCopy the code

Do this in webpack.config.js

.module.exports = {
  ...
  module: {
    rules: [{test: /\.css$/,
        use: [ MinniCssExtractPlugin.loader,'css-loader'.'postcss-loader'] // Add a post-loader}]}};Copy the code

Add a postcss.config.js file under the root directory

module.exports = {
    plugins: [
        require("autoprefixer") ({overrideBrowserslist: ["last 2 versions"."1%" >]]}});Copy the code

Run it againnpm run buildTo see themain.css, you can see that the vendor prefix has been added, so the packaging of CSS is here

  • Requirement: Background images should also be packed in
NPM I file-loader url-loader -d // or CNPM I file-loader url-loader -dCopy the code

Do this in webpack.config.js

.module.exports = {
  ...
  module: {
    rules: [{...test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader'.options: {
              limit: 50 * 1024.loader: 'file-loader'.esModule: false.outputPath: 'public/imgs'.name: '[name].[ext]'},},],},]}};Copy the code

Will we commented out in front of the background style, then perform a NPM run the build, there had been much under the dist directory dist/public/imgs/Chihiro. JPG, then in the browser to open the pack out index. The HTML, you can see, the background picture has come out

  • Requirements: After processing HTML, CSS, images, and js, convert to ES5

At present, the JS code that comes out of the package is just as it is, and not processed

NPM I babel-loader@babel/core@babel /preset-env @babel/plugin-proposal-class-properties -d // or CNPM I babel-loader @babel/core @babel/preset-env @babel/plugin-proposal-class-properties -DCopy the code

Do this in webpack.config.js

.module.exports = {
  ...
  module: {
    rules: [{...test: /\.js$/,
        use: {
          loader: 'babel-loader'.options: {
            presets: [
                '@babel/preset-env'].plugins:[
              ["@babel/plugin-proposal-class-properties", { "loose" : true}]]}}},]}};Copy the code

After configuration, execute againnpm run build, check out the packagemain.jsYou can see that the JS code has been converted

At this point, the packaging part is basically no need, but the front-end engineering, can not just packaging, and improve the development effect so there are the following requirements

  • Requirement: We need to be able to host a server locally so that we can automatically package the updated code as we develop
NPM I webpack-dev-server -d // or CNPM I webpack-dev-server -dCopy the code

Do this in webpack.config.js

.module.exports = {
  ...
  devServer: {
    port: 3000.contentBase: './dist'.// The address of the service (i.e. the location of our output file)
    open: true.// Automatically open the browser
    compress: true./ / gzip compression
    hot: true.// Enable hot update},...plugins: [...new webpack.HotModuleReplacementPlugin(),
  ],
};
Copy the code

Add a command in the scripts field of package.json

 "scripts": {..."dev": "webpack-dev-server --config ./webpack.config.js"
  },

Copy the code

This time NPM run dev is executed, and the project is automatically up and running at http://localhost:3000/, and can be updated after the project file changes

3.4 Optimization of project structure

The last section of the demonstration, has basically explained the configuration process, the future needs to expand the configuration on the above line.

Now all of our project files are under the root directory without distinction, which is unfavorable for future development and inconvenient to manage; Secondly, the configuration of webpack does not distinguish between development and production modes, and files can be split here

  • First, we restructure the project files

Create the SRC folder and build folder and adjust the file as shown below

After that, the references in the file need to be readjusted

//index.js
- import './style.css'
+ import './style/style.css'
Copy the code
/*style.css*/
- background-image: url('./Chihiro.jpg');
+ background-image: url('.. /assets/img/Chihiro.jpg');
Copy the code

webpack.config.jsThe changes are shown in figure

  • Then the WebPack configuration file environment partition is adjusted
// Install dependencies first
npm i webpack-merge -D
// or 
cnpm i webpack-merge -D
Copy the code

inbuildAdd two files under the directory, respectivelywebpack.dev.jsandwebpack.prod.js

// webpack.dev.js
const {merge} = require('webpack-merge')
const base = require('./webpack.config.js')
const path = require('path')

module.exports = merge(base, {
  mode: 'development'.devtool: 'cheap-module-source-map'.// This is where the source code was traced when the configuration error was reported
  devServer: {
    port: 3000.contentBase:  path.join(__dirname, '.. /dist'), // The address of the service (i.e. the location of our output file)
    open: true.// Automatically open the browser
    compress: true./ / gzip compression
    progress: true}})Copy the code
// webpack.prod.js
const {merge} = require('webpack-merge')
const base = require('./webpack.config.js')

module.exports = merge(base, {
  mode: 'production'
})
Copy the code

The original webpack.config.js removes the configuration of the devServer field and puts only the common configuration

The configuration file path of the command in package.json needs to be changed

  "scripts": {
    "build": "webpack --config ./build/webpack.prod.js"."dev": "webpack-dev-server --config ./build/webpack.dev.js"
  },
Copy the code

So far, the adjustment of the project structure has been completed.

Tutorial summary

Advantages:

  1. Pure: the project did not use the framework, using the native JS code, can exclude the influence of the framework, simple learning webPack front-end engineering configuration process

  2. Progressive: The project shows the implementation of the page step by step from the original HTML; Webpack configuration is also one by one requirements, one by one configuration, not all of a sudden to novice readers, so that readers can grasp the main process, better understand

Inadequate:

  1. Crude: The implementation of the page, with an elastic layout in Flex, can be problematic in some older browsers; Webpack configuration is much more than what I wrote in the tutorial, but the configuration is the same as above, if there is a need, check and configure (code sharding, code compression, CSS precompilation, etc.)

Dot a like or give a star bai, code word very tired, encourage once 🥰🥰🥰