美文网首页
webpack入门介绍(webpack 3.X)

webpack入门介绍(webpack 3.X)

作者: 无懈可击 | 来源:发表于2021-05-11 10:23 被阅读0次

    webpack入门介绍

    0、码云仓库代码(欢迎Start)

    码云仓库代码-https://gitee.com/hongjunyong/webpack-imooc-test

    1、基本介绍

    webpack是为什么?
    为什么要使用webpack?
    怎么配置webpack?
    

    1.1、webpack官方文档

    https://doc.webpack-china.org/
    https://github.com/webpack/webpack
    

    1.2、webpack概述

    js(ES6、typescript)的打包器、代码按需加载、loader加载器
    
    webpack-detail.png
    从图中我们可以看出,Webpack 可以将多种静态资源 js、css、less(不仅仅这些,还有像jade、less等等)转换成一个静态文件,减少了页面的请求。
    

    1.3、webpack版本变化

    webpack v1.0.0   ---    2014.2.20  编译打包、模块热更新、代码分割、文件处理
    webpack v2.2.0   ---    2017.1.18  打包文件体积更小、动态import、新的官方文档
    webpack v3.0.0   ---    2017.6.19  作用域提升(打包后的代码性能)、配合动态import使用
    webpack v4.0.0   ---    2018.2.27  打包的速度提升(构建时间降低了 60%-98%)、Mode 零配置以及默认值:development 或者是 production、entry默认:./src/index.js为入口文件,output默认:./dist/main.js
    
    time.png

    1.4、为什么webpack?

    1、最热门的三大框架:vue、react、angular,他们命令行工具都使用webpack构建工具
        Vue-cli
        Angular-cli
        React-starter
    2、代码分割:Code-splitting
    3、模块化(js模块化、css模块化【css设计模式,例如:SMACSS模式(减少代码量、简化代码维护)、oocss模式】)
    

    1.5、hello webpack(案例:1-1-first)

    demo.png

    1.6、安装

    npm install webpack@3.10.0 -g
    webpack4.0以上版本:npm install webpack-cli -g(交互式的初始化一个项目、迁移项目V1 -> V2[仅限配置文件])
    

    二、核心概念

    2.1、Entry :

    功能:1、代码入口;
         2、打包的入口;
         3、单个(业务代码、框架代码分开)或多个(多页面程序)
    

    示例:

        写法一、
        // 扩展性差
        module.exports = {
            entry: 'index.js'
        }
    
        写法二、
        // 扩展性差(两个文件、两个路径)
        module.exports = {
            entry: ['index.js', 'vendor.js']
        }
    
        写法三(推荐)、
        module.exports = {
          entry: {
            index: 'index.js',
            vendor: 'vendor.js'
          }
        };
    

    2.2、Output:

    功能:1、打包成的文件(bundle);
         2、一个或多个、自定义规则
    

    示例:

        // 一个入口对应一个出口
        module.exports = {
          entry: {
            index: 'index.js',
          },
          output: {
            filename: 'index.min.js'
          }
        };
        
        
        module.exports = {
          entry: {
            index: 'index.js',
            vendor: 'vendor.js'
          },
          // 例如:entry=index ==> index.min.js
          // 例如:entry=vendor ==> vendor.min.js
          // MD5:版本号
          output: {
            // 用于输出文件的文件名 MD5码(5代表有五位数)
            filename: '[name].min.[hash:5].js'
            // 目标输出目录 path 的绝对路径(此配置将一个单独的 bundle.js 文件输出到 /home/proj/public/assets 目录中)
            path: '/home/proj/public/assets'
          }
        };
    

    2.3、loader:

    功能:1、处理文件;
         2、转化为模块(例如loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript)
    示例:(rules执行的顺序从下到上)
    
        module.exports = {
            module: [
                rules: [
                    {
                        // 易错:这里的正则不带引用
                        test: /\.css$/,
                        use: 'css-loader',
                        // 排除在规则之外的
                        exclude: '/node_modules'
                    }
                ]
            ]
        }
    

    2.3.1、常用的loader

    编译相关:
        babel-loader、ts-loader
    样式相关:
        css-loader、style-loader、less-loader、postcss-loader
    文件相关:
        file-loader、url-loader
    

    2.4、plugin:

    功能:1、插件是 wepback 的支柱功能;
         2、参与打包整个过程;
         3、打包优化和压缩(打包公共代码,如果是多页面的程序,公用的代码会缓存到浏览器,减少对服务端的请求)
         4、配置编译时的变量
    示例:
    
        // 压缩代码
        const webpack = require('webpack');
        module.exports = {
            plugins: [
                new webpack.optimize.UglifyJsPlugin()
            ]
        }
    

    2.4.1、常用的plugins

        优化相关:
            commonsChunkPlugin:提取不同chunk(提取公共代码,形成一个公共的代码块)
            uglifyjsWebpackPlugin:压缩代码
        
        功能相关:
            extractTextWebpackPlugin:css提取出来作为一个单独的文件
            htmlWebpackPlugin:生成html
            hotModuleReplacementPlugin:模块热更新
            copyWebpackPlugin:拷贝文件(例如引用别人的插件,别人已经压缩打包好了)
    

    2.5、 名词解释

    Chunk:代码块(提取公共代码,形成一个公共的代码块)
    Bundle:一捆、一束:打包过的代码
    Module:模块
    

    3、webpack基本命令

    webpack -h 查看所有命令
    webpack -v 查看版本
    webpack entry<entry> output 或 webpack --config webpack.conf.js 打包js
    
    webpack-cli init webpack-addons-demo(webpack-addons前缀,demo项目名称): 交互式的初始化一个项目
    
    webpack-cli.png webpack-cli-pengwings.png

    4、 实战

    4.1、 打包js(案例:3-1-js 同 1-1-first)

    打包:webpack app.js bundle.js(app.js代表入口文件;bundle.js代表打包后生成的文件)
        webpack --config webpack.conf.js(文件名不是webpack.config.js,如果是的话,直接执行webpack命令)
    

    4.2、 编译ES6(案例:3-2-es6) 略

    npm init 项目初始化,添加package.json
    npm install babel-loader@8.0.0-beta.0 @babel/core 静态文件托管
    npm install @babel/preset-env --save-dev
    

    4.3、 编译typescript(案例:3-3-typescript) 略

    npm install webpack typescript ts-loader awesome-typescript-loader --save-dev
    
    npm install typescipt ts-loader --save-dev
    npm install typescipt awesome-typescript-loader --save-dev
    
    如果项目中有用到lodash
    npm install lodash --save
    

    4.4、 打包公共代码(案例:3-4-public)

    4.4.1、 作用

    减少代码冗余
    提高加载速度
    

    案例:


    public.png
    把C提取出来:如果用户访问了A并且加载了C,再当用户浏览了B,C就不用再去加载
    

    4.4.2、 应用场景:

    单页面就不需要再去加载
    多页面利用浏览器缓存
    

    4.4.3、 使用的插件 commonsChunkPlugin

    • 配置
    public2.png

    4.4.4、 使用步骤

    初始化:npm init
    安装本地依赖:npm install webpack --save-dev
    针对多个entry,如果只有一个entry是没有作用的(单页面更多的是用懒加载,懒加载有其他的打包方式)
    
        // 打包公共代码(第三方依赖 与 业务代码 混在一起)
        new webpack.optimize.CommonsChunkPlugin({
            name: 'common',
            // 代码出现2次就进行打包
            minChunks: 2
        })
    
        // 分离第三方依赖 与 分离业务代码
        new webpack.optimize.CommonsChunkPlugin({
            name: 'common',
            // 代码出现2次就进行打包
            minChunks: 2,
            // 需要指定要打包的公共代码
            chunks: ['pageA','pageB']
        }),
        new webpack.optimize.CommonsChunkPlugin({
            // vendor是第三方插件打包后的代码,manifest是自己封装的公共代码进行打包
            names: ['vendor','manifest'],
            // 把webpack的代码页打包进来,不需要在任何地方重复了
            minChunks: Infinity
        })
    

    4.5、 代码分割 和 懒加载(案例:3-5-splice)

    让用户浏览的时候加载更少的代码,用更短的时间看到页面
    AMD:依赖前置,提前执行
    CMD:尽可能懒执行
    

    4.5.1、 使用场景

    分离业务代码 和 第三方依赖
    分离业务代码 和 业务公共代码 和 第三方依赖
    分离首次加载 和 访问后加载的代码
    

    4.5.2、 pageA.js案例

        // 只有打包出一个pageA.bundle.js文件(混在一起)
        import * as _ from 'lodash'
        
        // ensure只是把lodash加载进来,并没有执行到lodash代码(lodash提取到vendor里)
        require.ensure(['lodash'], function () {
            // 这里才有执行到lodash代码
            var _ = require('lodash');
            _.join(['1', '2'], '3')
        },'vendor');
    
        // 提前include,这样moduleA就被提取到pageA.bundle.js里
        require.include('./moduleA');
        
        // 会生成subPageA.chunk.js、subPageB.chunk.js文件(但是moduleA没有被分离出来)
        var page = 'subPageA';
        if (page === 'subPageA'){
            require.ensure(['./subPageA'], function () {
                var subPageA = require('./subPageA')
            },'subPageA');
        } else if (page === 'subPageB') {
            require.ensure(['./subPageB'], function () {
                var subPageB = require('./subPageB')
            },'subPageB');
        }
    

    4.6、 css style-loader(案例:3-6-style-loader)

    帮助需要载入的页面创建style标签(也就是:使用<style>将css-loader内部样式注入到我们的HTML页面)
    webpack是自下而上解析的,只有通过css-loader处理css后才能通过style-loader生成<style></style>标签
    

    4.6.1 安装

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

    4.6.2 配置

        module: {
            rules: [
                {
                    test: /\.css$/,
                    use: [
                        {
                            // 放到HTML页面上
                            // useable可以动态让css插入或不插入页面中
                            loader: 'style-loader/useable',
                            options: {
                                // 让css代码插入到指定的DOM节点上(图1)
                                insertInto: '#app',
                                // 让样式结合到一个style标签上(图2)
                                singleton: true,
                                // css函数(图3、4、5)
                                transform: './css.transform.js'
                            }
                        },
                        {
                            // 把css交给css-loader,让他处理完js可以import css这块内容,再交给style-loader
                            loader: 'css-loader'
                        }
                    ]
                }
            ]
        }
            
        import base from './css/base.css'
        // 使用base样式
        base.use()
        // 不使用base样式
        base.unuse()
    

    (图1)


    style.png

    (图2)


    style2.png

    (图3)


    pc.png

    (图4)


    iphone.png

    (图5)


    transform.png

    4.7 css css-loader

    加载.css文件
    

    4.7.1 安装

    npm install css-loader --save-dev
    

    4.7.1 配置

        module: {
            rules: [
                {
                    test: /\.css$/,
                    use: [
                        {
                            loader: 'style-loader'
                        },
                        {
                            // 把css交给css-loader,让他处理完js可以import css代码,再交给style-loader(相当于引用css文件)
                            loader: 'css-loader',
                            options: {
                                // css被压缩(图1)
                                minimize: true,
                                // js代码中使用css样式(图2)
                                modules: true,
                                // 给class命名:路径 文件名 class名称 五位的编码(图3)
                                localIdentName: '[path][name]_[local]_[hash:base64:5]'
                            }
                        }
                    ]
                }
            ]
        }
        
        
        // css-loader要结合app.js:
        var app = document.getElementById('app');
        app.innerHTML = '<div class="'+ base.box +'"></div>'
    

    (图1)


    cssmin.png

    (图2)


    css-loader.png

    (图3)


    name.png

    4.7 配置less/sass(案例:3-7-less-sass)

    4.7.1 安装

    npm install less-loader less --save-dev
    
    //因为sass-loader依赖于node-sass,所以还要安装node-sass
    npm install sass-loader node-sass --save-dev 
    

    4.7.2 配置

        module: {
            rules: [
                {
                    test: /\.less$/,
                    use: [
                        {
                            // 放到HTML页面上
                            loader: 'style-loader',
                        },
                        {
                            // 把css交给css-loader,让他处理完js可以import css代码,再交给style-loader(相当于引用css文件)
                            loader: 'css-loader'
                        },
                        {
                            loader: 'less-loader'
                        }
                    ]
                }
            ]
        }
    

    4.8 提取css文件(案例:3-8-extract)

    style-loader、css-loader、less、sass都是把样式打包到js文件里,并不是生成独立的css文件,
    利用提取css文件,会在dist目录下生成app.min.css文件
    

    4.8.1 安装

    npm install extract-text-webpack-plugin webpack --save-dev
    
    加载:var ExtractTextWebpackPlugin = require('extract-text-webpack-plugin')
    
        plugins: [
            // 对(提取css文件)插件的调用
            new ExtractTextWebpackPlugin({
                // 打包后的名字
                filename: '[name].min.css',
                // 指定提取范围(如果是true是就把所有有引入的css文件都打包;如果是false,只会提取初始化的文件)
                allChunks: false
            })
        ]
        
        use: ExtractTextWebpackPlugin.extract({
            // 当不提取用什么方式加载到页面上(直接把样式插入到HTML页面上)
            fallback: {
                // 放到HTML页面上
                loader: 'style-loader'
            },
            // 继续处理的loader
            use: [
                {
                    // 把css交给css-loader,让他处理完js可以import css代码,再交给style-loader(相当于引用css文件)
                    loader: 'css-loader'
                },
                {
                    loader: 'less-loader'
                }
            ]
        })
        
        提取出来的代码不会在页面上引用,需要手动引入
        <link rel="stylesheet" href="./dist/app.min.css">
    

    4.9 PostCSS(案例:3-8-postcss)

    Autoprefixer:自动添加css前缀
    css-nano:优化、压缩css
    css-next:使用未来的css语法(例如calc)
    
    npm install postcss postcss-loader autoprefixer cssnano postcss-cssnext --save-dev
    
    • 核心配置:
        {
            // 放在less或sass预处理语言之前
            loader: 'postcss-loader',
            options: {
                // 表明接下来插件是给postcss用的
                ident: 'postcss',
                plugins: [
                    // require('autoprefixer')(),
                    // postcss-cssnext已经包含了autoprefixer
                    require('postcss-cssnext')()
                ]
            }
        }
        
        // 未来的css语法:
        :root {
            --mainColor: red;
        }
        a {
            color: var(--mainColor);
        }
    
    postcss.png

    4.10 Tree Shaking(案例:3-8-tree-shaking)

    摇树木(摇完叶子会掉下来):写项目的时候有的代码没有用到,项目上线的时候代码还存在,会存在资源浪费、等待时间加长
    

    4.10.1 使用场景:

    常规优化
    引入第三方库的某一个功能
    

    4.10.2 js Tree Shaking

        // 对没有用到的js代码进行过滤
        new webpack.optimize.UglifyJsPlugin()
    
    • 未使用前


      js-tree-shaking.png
    • 使用后(代码被压缩,且只能找到‘this is a’)


      js-tree-shaking-result.png

    4.10.3 css Tree Shaking

    npm install purifycss-webpack glob-all --save-dev
    
        // 要写在ExtractTextWebpackPlugin的后面
        new PurifyCSS({
            paths: glob.sync([
                path.join(__dirname, './*.html'),
                path.join(__dirname, './src/*.js')
            ])
        }),
    

    5.1 图片处理(案例:4-1-img)

    5.1.1 css中引入的图片(npm isntall file-loader)

    作用:如果没有引入,图片资源会找不到;同时图片资源没有被打包
    
        {
            test:/\.(png|jpg|jped|gif)$/,
            use: [
                {
                    // 引入的图片
                    loader: 'file-loader',
                    options: {
                        // 设置绝对路径(指定路径,例如图片路径为:aa/1.jpg)
                        // publicPath: 'aa/',
                        // 输出的路径放到dist目录下(暂时没用,因为默认放在dist目录下)
                        // outputPath: 'dist/',
                        // 图片会放在dist/assets/imgs里,如果没有设置true,会裸露在外面
                        useRelativePath: true
                    }
                }
            ]
        }
    
    file-loader.png

    5.1.2 base64编码(npm isntall url-loader)

        {
            test:/\.(png|jpg|jped|gif)$/,
            use: [
                {
                    // base64图片
                    loader: 'url-loader',
                    options: {
                        name: '[name]-min[hash:5].[ext]',
                        // 当图片大于多少K的时候,转换成base64 100000 10K
                        limit: 100000,
                        // 图片会放在dist/assets/imgs里,如果没有设置true,会裸露在外面
                        useRelativePath: true
                    }
                }
            ]
        }
    

    5.1.3 压缩图片(npm isntall img-loader)

        {
            loader: 'img-loader',
            options: {
                pngquant: {
                    // 压缩图片比例
                    quality: 80
                }
            }
        }
    
    • 压缩前(图片文件比较大)


      img-loader2.png
    • 压缩后(图片文件比较小)


      img-loader.png

    5.1.4 自动合成雪碧图(npm isntall postcss-sprites)

    多张图片合成一张,压缩的时候会根据图片的位置进行定位
    
    sprite.png
        {
            loader: 'postcss-loader',
            options: {
                ident: 'postcss',
                plugins: [
                    // 自动合成雪碧图
                    require('postcss-sprites')({
                        // 指定输出的路径
                        spritePath: 'dist/assets/imgs/sprites'
                    }),
                    require('postcss-cssnext')(),
                ]
            }
        },
    

    5.1.5 字体文件

        test: /\.(eot|woff|woff2|ttf|svg)$/,
            use: [
                {
                    loader: 'url-loader',
                    options: {
                        name: '[name]-[hash:5].[ext]',
                        limit: 5000,
                        publicPath: '',
                        useRelativePath: true
                    }
                }
            ]
        }
    

    5.1.6 处理第三方 JS 库

    三种引入方式:外网引入、npm安装、文件引入
    

    第一种:外网引入(直接写在页面上就可以使用)

            <script src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
    

    第二种:npm安装:npm install jquery --save

            // 在每一个模块注入$这个变量
            new webpack.ProvidePlugin({
                $: 'jquery'
            }),
    

    第三种:文件引入

    • 两处的jquery要对应
            // 在每一个模块注入$这个变量
            new webpack.ProvidePlugin({
                $: 'jquery'
            }),
    
    • 配合
            // 解析路径
            resolve: {
                alias: {
                    // jquery$:把jquery解析到某个路径下
                    jquery$: path.resolve(__dirname, 'src/libs/jquery-2.1.1.js')
                }
            },
    
    • app.js
            $('div').addClass('new');
    
    jquery.png

    5.2 生成HTML

    npm install html-webpack-plugin --save-dev
    
        var HtmlWebpackPlugin = require('html-webpack-plugin')
        
        plugins: [
            // 生成html
            new HtmlWebpackPlugin({
                // 生成后的文件名
                filename: 'index.html',
                // 指定页面进行生成
                template: './index.html',
                // 打包后的引用路径不会重复
                inject: false
            })
        ]
    
    引入图片
    npm install html-loader --save-dev
    

    THE END

    相关文章

      网友评论

          本文标题:webpack入门介绍(webpack 3.X)

          本文链接:https://www.haomeiwen.com/subject/dzrgdltx.html