webpack

什么是webpack

webpack可以看做是模块打包机,它做的事情是,分析你的项目结构,找到javascript模块以及其它的一些浏览器不能直接运行的拓展语言(less, typsscript等),并将其打包为合适的格式以供浏览器使用。

可以做的事情

  • 代码转换(将less转换为css,将es6转换为es5等)
  • 文件优化(压缩代码体积、合并文件等)
  • 代码分割(公共代码抽离、路由懒加载等)
  • 模块合并 (按照功能将多个模块合并成一个模块)
  • 自动刷新(本地起服务,进行热更新)
  • 代码校验(校验代码是否符合规范,eslint)
  • 自动发布

本课程最终能掌握webpack哪些内容

  • webpack常用配置
  • webpack高级配置
  • webpack优化策略
  • ast抽象语法树(如何解析语法层面的东西)
  • webpack中的Tapable(webpack就是各种勾子,而各种勾子是由tapable实现)
  • 掌握webpack流程,手写webpack
  • 手写webpack中常见的loader
  • 手写webpack中常见的plugin

webpack安装

安装本地的webpack和webpack-cli
yarn add webpack webpack-cli -D

webpack可以帮我们解析js模块,并且以当前js为准查找所有相关依赖的模块,把这些文件打包成一个文件,并且帮我们解决了浏览器模块的问题,即webpack自己实现了一套模块化的机制。

手动配置webpack

默认配置文件的名字webpack.config.js

/** webpack使用的是node语法 */ 

// webpack内置方法不需要额外安装
let path = require('path')  

module.exports = {
    // 打包模式,默认有production和development
    mode: 'development',  
    // 入口:从哪个文件开始进行依赖打包
    entry: './src/index.js', 
    output: {
        filename: 'bundle.js',  // 打包后的文件名
        // path.resolve: 将相对路径转换为绝对路径
        // path路径必须是一个绝对路径
        // __direname: 当前目录,即当前目录下的dist目录
        path: path.resolve(__dirname, 'dist'),  
    }
}

打包后的文件,即将模块以{key(模块文件名):value(方法体)}方式进行对象处理,递归的方式执行文件依赖,将多个模块打包为一个文件

(function (modules) { // webpack启动函数
    // 先定义一个模块缓存,若这个模块加载过则不需要再次加载,直接使用缓存
    var installedModules = {};

    // 配置实现了require方法
    function __webpack_require__(moduleId) {

        // 检查模块是否在缓存中
        if (installedModules[moduleId]) {
            return installedModules[moduleId].exports;
        }
        // 创建一个模块放入缓存中
        var module = installedModules[moduleId] = {
            i: moduleId,
            l: false,   // 是否缓存完成
            exports: {}
        };

        // 执行模块对应的执行函数
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

        // 模块缓存完成
        module.l = true;

        // 导出模块
        return module.exports;
    }

    // 递归加载模块文件
    return __webpack_require__(__webpack_require__.s = "./src/index.js");
})
({  
    // 所有的依赖模块对象,以{key: value}的形式
    // key(当前模块的路径)
    // value(模块对应的执行函数)
    "./src/index.js":
        (function (module, exports) {
            eval("console.log('hello word!!')\n\n//# sourceURL=webpack:///./src/index.js?");
        })
});

注意:若文件名不是webpack.config.js则需要执行

npx webpack --config custom.js

也可在package.json文件的scripts中配置脚本命令

“scripts": {
	”build": "webpack --config custom.js"
}

// 运行打包命令
npm run build
// 运行命令传参使用-- 
npm run build -- env=production

在本地启动服务

yarn add webpack-dev-server -D

// 启动服务
// webpack-dev-server并不会去打包文件,只是生成一个内存中的打包,将文件写到内存中。
npx webpack-dev-server

webpack.config.js配置文件

// 开发服务器的配置,即webpack-dev-server的配置
    devServer: {
        port: 3000, // 服务商品号
        progress: true,     // 启动服务时展示打包进度条
        contentBase: './build',  // 以build目录作为我们的静态服务器目录
        open: true,         // 自动启动服务器
        compress: true,     // 启动gzp压缩

    }

html模板文件

html-webpack-plugin:将html文件当作模板文件

// 安装依赖
yarn add html-webpack-plugin -D

// 配置webpack插件
// plugins存放所有的webpack插件
    plugins: [
        new HtmlWebpackPlugin({
            // 打包文件以template指定的文件为模板文件
            template: './src/index.html',
            // 打包后的模板文件名
            filename: 'index.html',
            // 模板文件压缩优化
            minify: {       
                // 将模板文件中的双引号删除
                removeAttributeQuotes: true, 
                // 将文件折叠成一行
                collapseWhitespace: true
            },
            // 将文件添加hash以解决缓存问题
            hash: true
        })
    ]

css处理

如何引入css文件呢,以前我们都是直接在html代码中将css文件引入,但现在html是个干净的模板文件,里面不能再引入css文件,应让css文件和js文件一样进行打包按需引入,所以css文件应该在js中引入

import ('./style.css')

但直接在js文件中引入,js代码是肯定不能识别css代码的,所以会报错确少对应的loader,故我们需要在webpack中对这个css模块进行配置处理。

 // 将所有的模块以合适的loader进行处理
    module: {
        // 模块对应的规则即loader处理
        rules: [
            {
                // 配置所有的css文件
                test: /\.css$/,
                // css-loader: 解析@import这种语法,将多个css文件合并为一个css
                // style-loader: 将css插入到模板文件的head标签中
                // loader的特点:每个loader的功能比较单一,仅专注的做一件事,所以use可以是一个数组,多个loader组合使用
                // loader的执行顺序:默认是从右向左,从下向上执行
                // use: ["style-loader", "css-loader" ]

                // loader也可以为对象的形式
                use: [
                    {
                        loader: "style-loader",
                        // loader的参数处理
                        options: {
                            // 将css文件插入到head文件上面,这样html模板中引入的默认样式便不会被覆盖
                            insertAt: 'top' 
                        }
                    },
                    "css-loader" 
                ]
            },
            {
                // less文件配置
                test: /\.less$/,
                use: [
                    "style-loader",
                    "css-loader",
                    "less-loader" // 将less编译为css
                ]
            }
            // sass文件配置顺序:node-sass, sass-loader
        ]
    }

上面的方式会将所有的样式插入到style标签中,但如果想抽离成link的形式需要使用mini-css-extract-plugin

plugins: [
        // 抽离css文件,将css编译后的文件以link的形式引入而非直接放至style标签中
        new MiniCssExtractPlugin({
            filename: "main.css",   // 抽离后的文件名
        })
],
module: {
	rules: [
		{
                test: /\.less$/,
                use: [
                    // "style-loader",
                    // 抽离css文件以link的方式引入
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                    // autoprefixer为样式添加前缀-webkit-等,以兼容各个浏览器,
                    // 前缀功能依赖于postcss-loader进行处理
                    // 同时需要创建postcss.config.js进行配置
                    "postcss-loader",
                    "less-loader" // 将less编译为css
                ]
            }
	]
}

// postcss.config.js配置
module.exports = {
    plugins: [require('autoprefixer')]
}

注意:MiniCssExtractPlugin不支持css文件压缩,需要使用optimize-css-assets-webpack-plugin

// css文件压缩
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
// js文件压缩优化
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

// 优化项处理
    optimization: {
        minimizer: [
            // js文件压缩优化
            new UglifyJsPlugin({
                cache: true,    // 是否进行缓存
                parallel: true,   // 是否并行打包,可以多文件同时进行打包
                sourceMap: true,    // 
            }),
            // css文件压缩
            new OptimizeCssAssetsPlugin(),
        ]
    }

js babel

module: {
        // 模块对应的规则即loader处理
        rules: [
            {
                test: /\.js$/,
                use: [
                    {
                        // 将高级语法(如es6)转化为es5
                        loader: 'babel-loader',
                        options: {
                            // 预设,也是plugins的一个大集合
                            presets: [
                                // 进行语法转换,如将es6转化为es5
                                "@babel/preset-env"
                            ],
                            // babel-loader所需的所有插件
                            plugins: [
                                // 用于解析装饰器@符
                                ["@babel/plugin-proposal-decorators", { "legacy": true }],
                                // 用于class类语法转换
                                ["@babel/plugin-proposal-class-properties"]
                            ]
                        }
                    }
                ]
            }
        ]
    }

你可能感兴趣的:(webpack基础配置)