webpack入门介绍(webpack 3.X)

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值