# webpack基础

# 初识webpack

代码

src/index.js

function add(x,y) {
    return x + y
}
add(1,2)

运行指令

  1. 开发环境:webpack ./src/indexjs -o ./build/build.js --mode=development;
  2. 生产环境:webpack ./src/indexjs -o ./build/build.js --mode=production;

webpack会以 ./src/index.js 为入口文件开始打包,打包后输出到 ./build/build.js

结论

  1. webpack能处理js/json资源,不能处理css/img等资源;
  2. 生产环境和开发环境将ES6代码编译成浏览器能识别的代码;
  3. 生产环境比开发环境多一个js代码压缩;

# webpack五个核心

创建webpack.config.js

  1. entry 入口目录
  2. output 输出目录
  3. loader
  4. plugins 插件
  5. mode 模式
/**
 * webpack.config.js webpack的配置文件
 * */
const { resolve } = require('path')

module.exports = {
    // 入口起点
    entry: './src/index',
    output: {
        // 输出文件名
        filename: "build.js",
        // 输出路径
        /**
         * __dirname nodejs的变量, 代表当前文件的目录的绝对路径
         */
        path: resolve(__dirname,'build')
    },
    // loader的配置
    module: {
        rules: [
            // 详细的loader配置
        ]
    },
    // plugins的配置
    plugins: [

    ],
    // 模式 development / production
    mode: "development"
}
# 注意:

loader: 1. 下载 2. 使用(配置loader)

plugins: 1 下载 2. 引入 3. 使用

# 打包样式资源

1. 打包样式资源需要配置loader

2. 需要 style-loader 、css-loader

3. 代码配置

// loader的配置
module: {
	rules: [
		// 详细的loader配置
        {
            // 匹配哪些文件
            test: /\.css$/,
            // 使用哪些loader
            use: [
                // use数组中loader执行顺序:从右到左, 从下到上 依次执行
                // 创建style标签,将js中的样式资源插入进行,添加到head中生效
               	'style-loader',
                // 将css文件变成一个commonjs模块加载到js中,里面内容是样式字符串
                'css-loader'
            ]
        },
        {
            test: /\.less$/,
            use: ['style-loader', 'css-loader', 'less-loader']
        }
	]
}

# 打包HTML资源

1. 安装 html-webpack-plugin

2. 使用

const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
    /**
	* 功能:默认会创建一个空的Html文件,引入打包输出的所有资源(JS/CSS)
	*/
	new HtmlWebpackPlugin({
        // 复制 "./src/index.html" 文件, 并自动引入打包输出的所有资源
        template: "./src/index.html",
	})
]

# 打包图片资源

// loader的配置
module: {
	rules: [
		{
			// 问题:处理不了html img标签图片 只能处理css background-image
            test: /\.(jpg|png|gif)$/,
            // url-loader 依赖于 file-loader
            loader: 'url-loader',
            options: {
                // 当图片大小小于8kb,就会被base64处理
                // 优点: 减少请求数量(减轻服务器压力)
                // 缺点: 图片体积会更大(文件请求速度更慢)
                limit: 8 * 1024,
                // 问题:因为url-loader默认es6模块化解析,而html-loader引入图片是commonjs
                // 解析时会出现问题:[object Module]
                // 解决:关闭url-loader的es6模块,使用commonjs解析
                esModule: false,
                // 给图片重命名
                // [hash:10] 取图片的hash的前10位
                // [ext] 取文件原来的扩展名
                name: '[hash:10].[ext]'
            }
        },
        {
            test: /\.html$/,
            // 处理html文件的img图片(负责引入img,从而能被url-loader处理)
            loader: 'html-loader'
        }
    ]
}

# 打包其他资源

// loader的配置
module: {
	rules: [
		// 打包其他资源(除了html/js/css资源以外的资源)
        {
            // 排除html/js/css资源
            exclude: /\.(css|js|html)$/,
            loader: 'file-loader',
            options: {
                name: '[hash:10].[ext]'
            }
        }
    ]
}

# devServer

module.exports = {
    // 开发服务器 devServer: 用来自动化(自动编译,自动打开浏览器,自动刷新浏览器)
    // 特点:只会在内存中编译打包,不会有任何输出
    // 启动devServer指令为:npx webpack-dev-server(需要下载 npm i webpack-dev-server)
    devServer: {
        contentBase: resolve(__dirname,'build'),
        // 启动gzip压缩
        compress: true,
        // 端口号
        port: 3000,
        // 自动打开浏览器
        open: true
    }
}

# 提取单独的css文件

之前的css文件打包后会在js文件里面,但有另一种方法可以提取单独的css文件

使用mini-css-extract-plugin

const {resolve} = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")

module.exports = {
    entry: './src/js/index.js',
    output: {
        filename: 'js/built.js',
        path: resolve(__dirname, 'build')
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    // 取代style-loader 作用: 提取js中的css成单独文件
                    MiniCssExtractPlugin.loader,
                    'css-loader'
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }),
        new MiniCssExtractPlugin({
            // 对输出的css文件重命名
            filename: 'css/built.css'
        })
    ],
    mode: 'development'
}

# css兼容性处理和压缩

css兼容性处理:postcss

  • 需要 npm i postcss-loader postcss-prset-env -D
  • postcss找到package.jsonbrowserslist里面的配置,通过配置加载指定的css兼容性样式
//package.json
"browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  }
  • browserslist 默认 production,如需使用development 则需要设置node环境变量:process.env.NODE_ENV = development
  • loader的配置
 {
     loader: "postcss-loader",
         options: {
             ident: "postcss",
                 plugins: () => [
                     // postcss的插件
                     require('postcss-preset-env')()
                 ]
         }
 }
  • css压缩需要下载插件npm i optimize-css-assets-webpack-plugin -D
  • 完整配置
const {resolve} = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsWebpackplugin = require("optimize-css-assets-webpack-plugin");

// 设置nodejs环境变量
// process.env.NODE_ENV = "development";

module.exports = {
    entry: './src/js/index.js',
    output: {
        filename: 'js/built.js',
        path: resolve(__dirname, 'build')
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    // 取代style-loader 作用: 提取js中的css成单独文件
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    // 第一种:使用loader的默认配置
                    {
                        loader: "postcss-loader",
                        options: {
                            ident: 'postcss',
                            plugins: () => [
                                // postcss的插件
                                require('postcss-preset-env')()
                            ]
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }),
        new MiniCssExtractPlugin({
            // 对输出的css文件重命名
            filename: 'css/built.css'
        }),
        // 压缩css
        new OptimizeCssAssetsWebpackplugin()
    ],
    mode: 'development'
}

# js语法检查eslint

  1. 语法检查需要两个插件 npm i eslint-loader eslint -D
  2. 注意:只检查自己写的源代码,第三方的库是不用检查的
  3. 设置检查规则:package.json中eslintConfig中设置
"eslintConfig": {
    "extends": "airbnb-base"
}
  1. 推荐airbnb检查规则,需要安装npm i eslint-config-airbnb-base eslint-plugin-import -D
  2. loader配置
module: {
    rules: [
        {
            test: /\.js$/,
            exclude: /node_modules/, // 排除
            loader: 'eslint-loader',
            options: {
				fix: true, // 自动修复eslint的错误
			}
        }
    ]
}

# js兼容性处理

js兼容处理:babel-loader @babel/preset-env @babel/core
	1. 基本的js兼容性处理 --> @babel/preset-env
		问题:只能转换基本语法,如promise高级语法不能转换
	2. 全部js兼容性处理 --> @babel/polyfill
		问题:我只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了~
	3. 需要做兼容性问题的就做:按需加载 core-js
	4. 一共需要安装 npm i babel-loader @babel/preset-env @babel/core @babel/polyfill core-js -D

# loader配置

{
    test: /\.js$/,
    exclude: /node_modules/, // 排除
    loader: 'babel-loader',
    options: {
        // 预设:指示babel做怎样的兼容处理
        presets: [
            '@babel/preset-env',
            {
                // 按需加载
                useBuiltIns: 'usage',
                // 指定core-js版本
                corejs: {
                    version: 3
                },
                // 指定兼容性做到哪个版本浏览器
                targets: {
                    chrome: '60',
                    firefox: '60',
                    ie: '9',
                    safari: '10',
                    edge: '17'
                }
            }
        ]
    }
}

# html和js压缩

# html压缩

在HtmlWebpackPlugin配置

new HtmlWebpackPlugin({
    template: './src/index.html',
    minify: {
        collapseWhitespace: true, // 移除空格
        removeComments: true // 移除注释
    }
})

# js压缩

将mode设置为生产环境production,而production会执行UglifJsPlugin进而压缩js代码