webpack基础知识

webpack基本概念

特点

  • 静态模块打包工具
  • 支持模块化

基本概念

  • 入口(entry)

    1
    2
    3
    4
    //webpack.config.js
    module.exports = {
    entry:'./src/index.js' //指定webpack的入口,使用该模块作为构建依赖图(dependency graph)的开始,进入该起点,找出依赖的模块和库
    }
  • 输出(output)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //webpack.config.js
    const path = require('path')

    moudule.exports = {
    entry:'./path/to/my/entry/file.js',
    output:{
    path:path.resolve(__dirname,"dist"),//指定打包后的文件位置
    filename:'my-webpack-bundle.js' //指定打包后的文件名
    }
    }
  • loader

    • webpack只能理解js和json文件,webpack处理其他类型的文件需要loader,通过loader将这些类型的文件转换为有效模块,添加到依赖图中

    • loader的属性

      • test:识别哪些类型的文件需要被转换
      • use:定义出转换时需要哪些loader
    • loader的使用

      • 安装相应的loader

        1
        npm install  --save-dev raw-loader
      • 配置loader

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        //webpack.config.js
        const path = require('path')

        moudule.exports = {
        entry:'./path/to/my/entry/file.js',
        output:{
        path:path.resolve(__dirname,"dist"),//指定打包后的文件位置
        filename:'my-webpack-bundle.js' //指定打包后的文件名
        },
        module:{
        rules:[{
        test:/\.txt$/i, //转换txt类型的文件
        use:'raw-loader'
        }]
        }
        }
  • plugin

    • plugin(插件)主要用于执行更广的任务,例如打包优化、资源管理、注入环境变量等额外的工作

    • plugin的使用

      • 安装需要的plugin

        1
        npm install --save-dev html-webpack-plugin
      • 配置plugin

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        //webpack.config.js
        const HtmlWebpackPlugin = require('html-webpack-plugin') //引入

        const path = require('path')

        moudule.exports = {
        entry:'./path/to/my/entry/file.js',
        output:{
        path:path.resolve(__dirname,"dist"),//指定打包后的文件位置
        filename:'my-webpack-bundle.js' //指定打包后的文件名
        },
        module:{
        rules:[{
        test:/\.txt$/i, //转换txt类型的文件
        use:'raw-loader'
        }]
        },
        //这个HtmlWebpackPlugin插件的作用是:生成一个html文件,并自动将生成的所有bundle模块注入到这个文件中,可以指定一个html模板,还可以指定其他参数
        plugins:[new HtmlWebpackPlugin({template:'./src/index.html'})]
        }
  • mode

    • mode(模式)指定开发环境:默认值为production

      • development:process.env.NODE_ENV == ‘development’
      • production::process.env.NODE_ENV == ‘production’
      • none
    • mode的使用

      1
      2
      3
      moudule.exports = {
      mode:'development'
      }
  • 浏览器兼容性(browser compatibility):符合ES5标准,不支持IE8-

  • 环境(environment):Webpack5运行于Nodejs v10.13.0+

webpack配置

安装webpack

1
2
3
4
5
6
7
8
9
10
#局部安装
npm install --save-dev webpack
//安装指定版本
npm install --save-dev webpack@x

//命令行工具可以安装webpack-cli
npm install --save-dev webpack-cli

#全局安装(不推荐),避免影响当前项目
npm install --global webpack

入口起点(entry points)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//webpack.config.js

module.exports = {
entry:'./src/index.js'
}
//相当于
module.exports = {
entry:{
main:'./src/index.js'
}
}

//配置多个文件
module.exports = {
entry:['./src/index1.js','./src/index2.js']
}
//对象语法
module.exports = {
entry:{
app:'./src/app.js',
home:'./src/home.js'
}
}

//描述入口文件
module.exports = {
entry: {
a2: 'dependingfile.js', //指定要输出的文件名
b2: {
runtime: 'x2', //运行时 chunk 的名字
dependOn: 'a2', //当前入口所依赖的入口。它们必须在该入口被加载前被加载
import: './b', //启动是需要加载的模块
},
},
};

出口(output)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//webpack.config.js

//单独文件
module.exports = {
output: {
filename: 'bundle.js'
}
};
//多个文件
module.exports = {
entry: {
app: './src/app.js',
search: './src/search.js',
},
output: {
filename: '[name].js', //[]占位符,避免重复
path: __dirname + '/dist',
},
};
// 最后打包的出口文件写入到硬盘:./dist/app.js, ./dist/search.js

//CDN
module.exports = {
//...
output: {
path: '/home/proj/cdn/assets/[fullhash]',
publicPath: 'https://cdn.example.com/assets/[fullhash]/',
},
};

loader

  • 安装:需要转换哪种类型的文件就安装对应的loader

    1
    npm install --save-dev css-loader ts-loader
  • 配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    //webpack.config.js

    module.exports = {
    module: {
    rules: [
    { test: /\.css$/i, use: 'css-loader' },
    { test: /\.ts$/i, use: 'ts-loader' },
    ],
    },
    };

    //其他配置,允许指定多个loader用于转换
    module.exports = {
    module: {
    rules: [
    {
    test: /\.css$/i,
    use: [ //loader从右往左读取,sass->css->style,最终完成样式文件处理
    { loader: 'style-loader' },
    {
    loader: 'css-loader',
    options: {
    modules: true
    }
    },
    { loader: 'sass-loader' }
    ]
    }
    ]
    }
    };
  • 特性

    • loader 支持链式调用,链中的每个 loader 会将转换应用在已处理过的资源上
    • loader 可以是同步的,也可以是异步的
    • loader 运行在 Node.js 中,并且能够执行任何操作
    • loader 能够产生额外的任意文件
  • loader原理

    • 从 npm install, node_modules 进行加载

    • loader模块导出一个函数

      1
      2
      3
      4
      5
      //my-loader.js

      module.exports = function (source) {
      return source
      }
  • 常用loader

    • 样式:style-loader、css-loader、less-loader、sass-loader等
    • 文件:raw-loader、vue-loader、file-loader 、url-loader等
    • 编译:babel-loader、coffee-loader 、ts-loader等
    • 校验测试:mocha-loader、jshint-loader 、eslint-loader等
  • 常用loader配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    module.exports = {
    module:{
    rules:[{
    test:'/\.css$/i',
    use:['style-loader','css-loader']
    },
    {
    test:'/\.less$/i',
    use:['style-loader','css-loader','less-loader']
    },
    {
    test:'/\.s[ac]ss$/i',
    use:['style-loader','css-loader','sass-loader']
    },
    {
    test:'/\.vue/i',
    use:['vue-loader']
    },
    {
    test:'/\.html?$/i',
    use:['html-loader']
    },{
    test:/\.(jpe?g|png|gif)$/i,
    use:{
    loader:'file-loader',
    options: {
    // 定义打包后文件的名称;
    name: '[name]_[hash].[ext]', // [name]:原文件名,[hash]:hash字符串(如果不定义名称,默认就以hash命名,[ext]:原文件的后缀名)
    outputPath: 'images/' // 定义图片输出的文件夹名(在output.path目录下)
    }
    }
    },{
    test:/\.(jpe?g|png|gif)$/i,
    use:{
    loader:'url-loader',
    options: {
    // 定义打包后文件的名称;
    name: '[name]_[hash].[ext]', // [name]:原文件名,[hash]:hash字符串(如果不定义名称,默认就以hash命名,[ext]:原文件的后缀名)
    outputPath: 'images/', // 定义图片输出的文件夹名(在output.path目录下)
    limit: 204800 // 大于200kb(200*1024=204800) 的图片会被打包在images文件夹里面,小于这个值的会被以base64的格式写在js文件中
    }
    }
    }]
    }
    }

plugin

  • 安装:需要哪些扩展功能就安装对应的plugin

    1
    npm install --save-dev html-webpack-plugin
  • 配置

    1
    2
    3
    moudule.exports = {
    plugins:[new HtmlWebpackPlugin()]
    }
  • 原理

    • 模块导出一个对象

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      // MyPlugin.js
      class MyPlugin {
      constructor(){
      console.log()
      }
      apply(compiler){

      }
      }
      module.exports = MyPlugin
  • 常用plugin

    • html-webpack-plugin:可以根据模板自动生成html代码,并自动引用css和js文件
    • mini-css-extract-plugin:将js文件中引用的样式单独抽离成css文件
    • DefinePlugin:编译时配置全局变量,webpack内置plugin
    • BannerPlugin:每个文件头部添加一些信息,webpack内置plugin
    • HotModuleReplacementPlugin:热更新(HMR),webpack内置plugin
  • 常用plugin配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const {CleanWebpackPlugin} = require('clean-webpack-plugin') //每次打包,先清理dist文件夹
    const {DefinePlugin} = require('webpack') //webpack自带plugin,定义全局变量
    const MiniCssExtractPlugin = require('mini-css-extract-plugin') //提取CSS

    module.exports = {
    modules:{
    rules:{
    test:'\.css$/i',
    use:[MiniCssExtractPlugin.loader,'css-loader']
    }
    },
    plugins:[
    new HtmlWebpackPlugin({
    template: path.resolve(__dirname, './index.html')
    }),
    new CleanWebpackPlugin(),
    new DefinePlugin({
    BASE_URL:'"./"'
    }),
    new MiniCssExtractPlugin({
    filename: '[name].[contenthash].css',
    })
    ]
    }