​从其他领域过来瞻仰大前端时代的辉煌,一般都会特别疑惑,index.js``decfd4cb58ba3c6cc8c2.chunk.js,e2a0f18f238432e4c037.css,这些都是啥?这又是啥?Why?Why?这一切都是webpack干的好事。

webpack 是一个现代 JavaScript 应用程序的静态打包工具。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),去每一个文件中递归找依赖,其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle

1.webpack到底是什么?

前端资源加载/打包工具

js→js→png→less→sass

  • 静态分析模块的依赖关系
  • 组织合并打包生成对应的静态资源

2.webpack4新特性

2.1 mode属性

  • development

    • 浏览器调试工具
    • 注释、开发阶段的详细错误日志和提示
    • 快速和优化的增量构建机制
  • production

    • 开启所有的优化代码
    • 更小的bundle大小
    • 去除掉只在开发阶段运行的代码
    • Scope hoisting(作用域)和Tree-shaking(引入但是没有使用,抖掉)

    webpack --mode development

2.2 开箱即用webassembly

2.3 支持多种模块类型

  • javascript/auto
  • javascript/esm
  • javascript/dynamic
  • json
  • webassembly/experimental

2.4 0CJS-0配置

0配置,webpack4Parcel打包工具启发,尽可能的让开发者运行项目的成本变低。webpack4不再强制需要webpack.config.js作为打包的入口配置文件,默认的入口为./src/和默认的出口./dist,小项目的福音。

2.5 新的插件系统

提供了针对插件和钩子的新API。

  • 所有的hook由hooks对象统一管理,它将所有的hook作为可扩展的类属性。
  • 当添加插件时,必须提供一个插件名称
  • 开发插件时,可以选择sync/callback/promise作为插件类型
  • 可以通过this.hooks={myHook:new SyncHook(...)}来注册hook了

2.6 node.js>=8.9.4

3.安装

3.1本地安装

cnpm install --save-dev webpack

npm install --save-dev webpack-cli

3.2全局安装(摒弃)

npm install --global webpack

  • 不推荐全局安装 webpack。这会将你项目中的 webpack 锁定到指定版本,并且在使用不同的 webpack 版本的项目中,可能会导致构建失败。

4.Quick Start

4.1新建文件夹

mkdir webpack-demo

4.2新建文件

index.js

/**
 * es6
 * 写法
 *  
 * */
import { hello } from './hello_module'
hello.sayHello()

/**
 * node.js
 * 写法
 */
// let hello=require('./hello_module')
// hello.sayHello();

hello_module.js

/**
 * es6
 */
 export default{
     sayHello:function () {
         console.log("hello")
     }
 }


/**
 * nodejs
 */
module.exports = {
    sayHello: function () {
        console.log("hello")
    }
}

4.3打包

.\node_modules\.bin\webpack --mode development index.js -o output_test_d.js 5kb

.\node_modules\.bin\webpack --mode production index.js -o output_test_p.js 2kb

5.配置文件

webpack.config.js

const path=require('path')

module.exports={
    entry:'./input.js', //入口文件
    output:{
        path:path.resolve(__dirname,'dist'),
        filename:'output.bundle.js'
    }
}
const path=require('path')

module.exports={
    entry:{
        home:'./home.js'
        about:'./about.js'
        other:'./other.js'
    }, //入口文件
    output:{
        path:path.resolve(__dirname,'dist'),
        filename:'[name].bundle.js' //name->home or about or other
    },
    mode:"development"
}

$:webpack

6.Loaders

webpack预处理源文件,例如ts->js

  • Files
  • JSON
  • Transpiling
  • Templating
  • Styling
  • Linting&&Testing
  • Frameworks

6.1 url-loader

当文件的大小小于某个指定size时,转成DataURL ,base64,不做雪碧图。

npm install url-loader --save-dev

import img from './image.png'

//webpack.config.js
module: {
        rules: [{
            test: /\.(png|jpg|gif)$/i,
            use: [{
                loader: 'url-loader',
                options: {
                    limit: 8192
                }
            }]
        }]
    }//当文件是png,jpg,gif时,会使用url-loader来进行处理,文件小于8k时,会把文件以DataUrl的形式存储在文件中

6.2 babel-loader

负责把es6,es7的代码转化为es5的代码

  • 安装

npm install -D babel-loader @babel/core @babel/preset-env webpack

moudule:{
    rules:[
        {
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
    ]
}

6.3 sass-loader

npm install sass-loader node-sass -D

npm install style-loader css-loader --save-dev

//webpack.config.js
module.exports={
    ..
    module:{
    	rules:[{
    		test:/\.scss$/,
    		use:[
    			"style-loader",
    			"css-loader",
    			"sass-loader"
    		]
		}]
	}
}

7.Plugins插件

7.1 MinCssExtractPlugin.loader

css合并到一起

  • 安装

npm install mini-css-extract-plugin -D

const path = require('path')
const MiniCssExtractPlugin=require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== 'production';

module.exports = {
    entry: {
        output: './src/index.js'
    }, //入口文件
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].bundle.js' //name->home or about or other
    },
    // mode: "production",
    mode:"development",
    plugins:[
        new MiniCssExtractPlugin({
            filename:"[name].[hash].css",//name->home
            chunkFilename:"[id].[hash].css"
        })
    ],
    module: {
        rules: [
            {
                test: /\.(png|jpg|gif)$/i,
                use: [{
                    loader: 'url-loader',
                    options: {
                        limit: 8192
                    }
                }]
            }
            ,
            {
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
            ,
            {
                test: /\.scss$/,
                use: [
                    // "style-loader",
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                    "sass-loader"
                ]
            }
        ]
    }
}

7.2 DefinePlugin-减少代码冗余,定义全局变量

const path=require('path');
const MiniCssExtractPlugin=require("min-css-extract-plugin");
const webpack=require('webpack')

module.exports={
    entry:{
        home:'./home.js'
        about:'./about.js'
        other:'./other.js'
    }, //入口文件
    output:{
        path:path.resolve(__dirname,'dist'),
        filename:'[name].bundle.js' //name->home or about or other
    },
    mode:"development",
    plugins:[
        new MiniCssExtractPlugin({
            filename:"[name].css",//name->home
            chunkFilename:"[id].css"
        }),
        new webpack.DefinePlugin({      'SERVICE_URL':JSON.stringify('http://www.sina.com')
        })//就可以直接在js文件中使用SERVICE_URL中使用
    ],
    module:{
    	rules:[{
    		test:/\.scss$/,
    		use:[
    			MinCssExtractPlugin.loader,
    			"css-loader",
    			"sass-loader"
    		]
		}]
	}
}

7.3 HtmlWebpackPlugin

  • 目的:帮助我们去生产html文件,我们的js脚本不能独立运行(仅限前端,都知道有node,是可以的独立运行的),所以js必须包含在某个HTML文件中,才能运行。

  • 安装

npm install --save-dev html-webpack-plugin

npm install html-webpack-plugin -D

const path = require('path')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== 'production';
const webpack=require('webpack')
const HtmlWebpackPlugin=require('html-webpack-plugin')

module.exports = {
    entry: {
        output: './src/index.js'
    }, //入口文件
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].bundle.js' //name->home or about or other
    },
    // mode: "production",
    mode: "development",
    plugins: [
        new MiniCssExtractPlugin({
            filename: "[name].[hash].css",//name->home
            chunkFilename: "[id].[hash].css"
        }),
        new webpack.DefinePlugin({
            'SERVICE_URL': JSON.stringify('https://dev.example.com')
        }),
        // new HtmlWebpackPlugin()//base
        new HtmlWebpackPlugin({
            title:"Randy App",
            filename:"index.html",
            template:'template.html'
        })
    ],
    module: {
        rules: [
            {
                test: /\.(png|jpg|gif)$/i,
                use: [{
                    loader: 'url-loader',
                    options: {
                        limit: 8192
                    }
                }]
            }
            ,
            {
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
            ,
            {
                test: /\.scss$/,
                use: [
                    // "style-loader",
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                    "sass-loader"
                ]
            }
        ]
    }
}

8.热替换-自动刷新

  • 配置完整的webpack项目,启动服务,热替换操作,自动化,页面更新也是自动化

  • 中文文档

  • 英文文档

  • 安装

npm install webpack-dev-server -D

const path = require('path')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== 'production';
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    entry: {
        output: './src/index.js'
    }, //入口文件
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].bundle.js' //name->home or about or other
    },
    devServer: {
        open:true,
        contentBase: path.join(__dirname, "dist"),//output 路径
        compress: true,//
        port: 3000
        // ,hot:false
        //hot配置是否启用模块的热替换功能,
        //devServer的默认行为是在发现源代码被变更后,
        //通过自动刷新整个页面来做到事实预览,
        
        //而开启hot后,
        //将在不刷新整个页面的情况下通过新模块替换老模块来做到实时预览。
    },
    // mode: "production",
    mode: "development",
    plugins: [
        new MiniCssExtractPlugin({
            filename: "[name].[hash].css",//name->home
            chunkFilename: "[id].[hash].css"
        }),
        new webpack.DefinePlugin({
            'SERVICE_URL': JSON.stringify('https://dev.example.com')
        }),
        // new HtmlWebpackPlugin()//base
        new HtmlWebpackPlugin({
            title: "Randy App",
            filename: "index.html",
            template: 'template.html'
        })
    ],
    module: {
        rules: [
            {
                test: /\.(png|jpg|gif)$/i,
                use: [{
                    loader: 'url-loader',
                    options: {
                        limit: 8192
                    }
                }]
            }
            ,
            {
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
            ,
            {
                test: /\.scss$/,
                use: [
                    // "style-loader",
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                    "sass-loader"
                ]
            }
        ]
    }
}
{
  "scripts": {
    "start": "webpack-dev-server --hot",
    "build":"webpack",
    "dev":"webpack-dev-server"
  },
  "devDependencies": {
    "@babel/core": "^7.8.4",
    "@babel/preset-env": "^7.8.4",
    "babel-loader": "^8.0.6",
    "css-loader": "^3.4.2",
    "fibers": "^4.0.2",
    "html-webpack-plugin": "^3.2.0",
    "mini-css-extract-plugin": "^0.9.0",
    "node-sass": "^4.13.1",
    "sass": "^1.25.0",
    "sass-loader": "^8.0.2",
    "style-loader": "^1.1.3",
    "url-loader": "^3.0.0",
    "webpack": "^4.41.6",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3",
     "file-loader": "^5.1.0",
    "url-loader": "^3.0.0"
  }
}

热启动:npm run start