Webpack4 快速上手

作者: 爱写Bug的程序猿 | 来源:发表于2019-07-11 10:55 被阅读53次

    Webpack 基础

    为什么要使用Webpack

    • 转换ES6语法
    • 转换JSX
    • CSS前缀补全/预处理器
    • 压缩整合
    • 图片压缩

    前端构建演变

    -> ant + YUI Tool -> Grunt -> Fis3
    -> Gulp -> Rollup
    -> Webpack
    ​ -> Parcel

    为什么选择Webpack

    • 社区生态丰富
    • 配置灵活和插件化扩展
    • 官方更新迭代速度快

    初识Webpack

    • 默认的配置文件:webpack.config.js

      ​ 可以通过webpack –config <指定文件>

    • 配置文件组成

    module.exports = {
        entry:'./src/index.js', //入口文件
        output:'./dist/main.js', //打包输出
        mode:'production', //环境
        module:{
            rules:[ //Loader配置
                {test:/\.txt$/,use:'raw-loader'}
            ]
        },
        plugins:[ //插件配置
            new HtmlwebpackPlugin({
                template:'./src/index.html'
            })
        ]
      }
      
    

    核心概念

    Entry

    ​ 作为入口配置,简单来说就重那个文件开始打包。

    用法:

    • 单入口
      module.exports={
        entry:'./path/file.js'
      }
    
    • 多入口
      module.exports={
        entry:{
            app:'./src/app.js',
            adminApp:'./src/adminApp.js'
        }
      }
    

    Output

    ​ 将打包后的文件输出到哪里。

    用法:

    • 单出口
      module.exports={
        entry:'./path/file.js',
        output:{
              filename:'bundle.js',
              path:__dirname+'/dist'
        }
      }
    
    • 多出口
      module.exports={
        entry:{
            app:'./src/app.js',
            adminApp:'./src/adminApp.js'
        },
          output:{
            filename:'[name].js',
              path:__dirname+'/dist'
        }
      }
    

    Loaders

    ​ webpack开箱即用只支持js和json这两种文件类型。像VUE,JSX这些webpack是不支持的,所以就有了Loader。简单来说Loaders就是处理文件的。

    ​ Loader本身就是一个函数,接收源文件作为参数然后在返回结果。

    常见Loader

    名称 描述
    babel-loader 转换ES5+的语法(需要babel的配合)
    css-loader 支持css文件的加载解析
    less-loader 将less转为css
    ts-loader 将ts转为js
    file-loader 将文件(图片、字体)等打包
    raw-loader 将文件以字符串形式导入
    thread-loader 多进程打包js和css
    url-loader 与file-loader功能一样,但是他是可以配置的,简单来说升级版file-loader

    用法

    module.exports = {
        entry:'./src/index.js', //入口文件
        output:'./dist/main.js', //打包输出
        mode:'production', //环境
        module:{
            rules:[ //Loaders配置
                {test:/\.txt$/,use:'raw-loader'}
            ]
        }
    }
    

    Plugins

    ​ 增强Webpack的功能,将打包后的文件进行优化、资源管理、环境变量的注入等待。简单来说就是Loaders做不了的用Plugins来做。

    ​ 作用用整个构建过程。

    常用的插件

    名称 描述
    CommonsChunkPlugin 将多个出口引用相同的文件进行提取。
    CleanWebpackPlugin 清理构建目录
    ExtractTextWebpackPlugin 将css从bundle中提取成一个独立的css文件
    CopyWebpackPlugin 将文件或文件夹拷贝到构建的目录中
    HtmlWebpackPlugin 创建html文件去承载bundle
    UglifyjsWebpackPlugin 压缩js(默认是开启的不需要配置)
    ZipWebpackPlugin 将构建资源生成为zip包
    HotModuleReplacementPlugin 热更新
    MiniCssExtractPlugin 将css提取成独立的文件(与style-loader会产生冲突)
    OptimizeCssAssetsWebpackPlugin 用于压缩css(配合 cssnano 加载器使用)

    说明:安装插件时要将所有的大写改为小写并且在非第一个大写字母前加短横线-。

    用法

    module.exports = {
        entry:'./src/index.js', //入口文件
        output:'./dist/main.js', //打包输出
        mode:'production', //环境
        module:{
            rules:[ //Loader配置
                {test:/\.txt$/,use:'raw-loader'}
            ]
        },
        plugins:[ //插件配置
            new HtmlwebpackPlugin({
                template:'./src/index.html'
            })
        ]
    }
    

    Mode

    ​ mode是在webpack4提出的一个概念,通过mode来指定当前的构建环境,比如:你现在是development(开发)环境,或者是production(生成环境默认).

    选项 描述
    development 开发环境
    production 生产环境
    none 不开启

    例子

    解析ES6

    # 安装依赖
    npm i -g webpack webpack-cli
    npm i -D @babel/core @babel/preset-env babel-loader
    # @babel/core       babel核心文件(必须安装)
    # @babel/preset-env babel用来转换ES5
    # babel-loader      webpack的loader,调用babel的
    
    //webpack.config.js
    module.exports={
        entry:"./src/app.js",
        output:{
            filename:bundle.js,
            path:__dirname+'/dist'
        },
        mode:'development',
        module:{
            rules:[
                {
                    test:/.js$/,
                    use:'babel-loader'
                }
            ]
        }
    }
    
    //.babelrc
    {
        "presets":[
            "@babel/preset-env"
        ]
    }
    

    解析CSS

    # 安装依赖
    npm i css-loader style-loader -D
    # css-loader    将css文件打包成commonjs对象
    # style-loader  将css-loader打包好的样式通过<style>标签插入到head中
    
    //webpack.config.js
    module.exports={
        entry:"./src/app.js",
        output:{
            filename:"bundle.js",
            path:__dirname+"/dist"
        },
        mode:"development",
        module:{
            rules:[
                {
                    test:/.js$/,
                    use:'babel-loader'
                },
                {
                    test:/.css$/,
                    use:[
                        'style-loader',
                        'css-loader'
                    ]
                    /*注意:
                    use内的loader执行是从下到上的,
                    所以先执行css-loader然后才是style-loader*/
                }
            ]
        }
    }
    

    解析Less

    # 安装依赖
    npm i css-loader style-loader less-loader less -D
    # css-loader    将css文件打包成commonjs对象
    # style-loader  将css-loader打包好的样式通过<style>标签插入到head中
    # less-loader   是将less转成css
    # less          less核心(必装),less-loader依赖
    
    //webpack.config.js
    module.exports={
        entry:"./src/app.js",
        output:{
            filename:"bundle.js",
            path:__dirname+"/dist"
        },
        mode:"development",
        module:{
            rules:[
                {
                    test:/.js$/,
                    use:'babel-loader'
                },
                {
                    test:/.less$/,
                    use:[
                        'style-loader',
                        'css-loader',
                        'less-loader'
                    ]
                    /*注意:
                    use内的loader执行是从下到上的,
                    首先将less转换成css
                    然后将css转换成js
                    然后将js封装为style标签
                }
            ]
        }
    }
    

    解析文件

    # 安装依赖
    npm i css-loader style-loader file-loader -D
    # css-loader    将css文件打包成commonjs对象
    # style-loader  将css-loader打包好的样式通过<style>标签插入到head中
    # file-loader   将文件解析
    
    //webpack.config.js
    module.exports={
        entry:"./src/app.js",
        output:{
            filename:"bundle.js",
            path:__dirname+"/dist"
        },
        mode:"development",
        module:{
            rules:[
                {
                    test:/.js$/,
                    use:'babel-loader'
                },
                {
                    test:/.css/,
                    use:[
                        'style-loader',
                        'css-loader'
                    ]
                    /*注意:
                    use内的loader执行是从下到上的,
                    首先将less转换成css
                    然后将css转换成js*/
                },
                {
                    test:/.(png|jpg|gif|jpeg|ttf|eot)$/,
                    use:[
                        'file-loader'
                    ]
                }
            ]
        }
    }
    

    更好的解析文件

    # 安装依赖
    npm i css-loader style-loader url-loader -D
    # css-loader    将css文件打包成commonjs对象
    # style-loader  将css-loader打包好的样式通过<style>标签插入到head中
    # url-loader    更好的文件解析,代替file-loader
    
    //webpack.config.js
    module.exports={
        entry:"./src/app.js",
        output:{
            filename:"bundle.js",
            path:__dirname+"/dist"
        },
        mode:"development",
        module:{
            rules:[
                {
                    test:/.js$/,
                    use:'babel-loader'
                },
                {
                    test:/.css/,
                    use:[
                        'style-loader',
                        'css-loader'
                    ]
                    /*注意:
                    use内的loader执行是从下到上的,
                    首先将less转换成css
                    然后将css转换成js*/
                },
                {
                    test:/.(png|jpg|gif|jpeg|ttf|eot)$/,
                    use:[
                        {
                            loader:'url-loader',
                            options:{
                                limit:10240 //单位B
                            }
                            /*
                                url-loader 与file-loader功能一样,不过他有一定很不错,
                                可以传入参数:
                                    limit:单位字节,如果文件小于给定的字节大小,就进行
                                    base64转换
                            */
                        }
                    ]
                }
            ]
        }
    }
    

    自动打包

    两种方法:

    • 命令行:webpack —watch
    • 配置文件:watch:true

    原理:

    ​ webpack轮询(每隔一定的时间)对当前文件夹下的文件的修改时间进行监听,如果某个文件发生了变化,webpack不会立即打包而是在缓存时间到后才去打包。

    //webpack.config.js
    module.export = {
        watch:true,//开启监听
        watchOptions:{
            ignored:/node_modules/.//默认为空,表示不对什么文件夹或文件监听,支持正则表达式        aggregateTimeout:300,//监听触发后等300ms后执行打包,默认300ms
            poll:1000,//轮询时间,单位ms
        }
    }
    

    热重载

    方法一

    webpack-dev-server开发者服务

    优势:

    • webpack-dev-server不刷新浏览器
    • webpack-dev-server文件放到内存

    依赖插件:

    ​ HotModuleReplacementPlugin

    ​ HMRP 是将打包后的文件放到内存里,通过websocket将内容发给浏览器,实现热重载。

    操作:

    //webpack.config.js
    const {HotModuleReplacementPlugin} = require('webpack');
    
    module.exports={
        entry:"./src/app.js",
        output:{
            filename:"bundle.js",
            path:__dirname+"/dist"
        },
        mode:"development",
        module:{
            rules:[
                {
                    test:/.js$/,
                    use:'babel-loader'
                },
                {
                    test:/.less$/,
                    use:[
                        'style-loader',
                        'css-loader',
                        'less-loader'
                    ]
                },
                {
                    test:/.(png|jpg)$/,
                    use:[
                        {
                            loader:'url-loader',
                            options:{
                                linmit:1024
                            }
                        }
                    ]
                }
            ]
        },
        plugins:[
            new HotModuleReplacementPlugin()
        ],
        devServer:{
            contentBase:'./dist',//服务器根目录
            hot:true //是否热重载
        }
    }
    
    # 执行命令
    npm i webpack-dev-server -g
    webpack-dev-server --open
    # --open 表示打开浏览器
    

    方法二

    /**
     * 另一种热重载的方法
     */
    const express = require('express');
    const webpack = require('webpack');
    const webpackDevMiddleware = require('webpack-dev-middleware');
    const app = express();
    
    const config = require('./webpack.config');
    
    app.use(webpackDevMiddleware(
        webpack(config),
        {
            publicPath:config.output.publicPath
        }
        ));
    
    app.listen(8080, () => {
        console.log('Example app listening on port 8080!');
    });
    
    //Run app, then load http://localhost:8080 in a browser to see the output.
    

    文件指纹

    ​ 打包后输出的文件名额外添加的后缀字符。

    有什么用:
    • 文件的版本管理。
    • 文件缓存。
    文件指纹如何生成
    • hash:根据修改时间生成。
    • chunkhash:根据entry生成。
    • contenthash:根据文件内容生成。
    如何用
    占位符 含义
    [ext] 后缀名
    [name] 文件名称
    [path] 文件的相对路径
    [chunkhash] 根据entry生成hash
    [folder] 文件所在的文件夹
    [contenthash] 文件内容hash,默认md5
    [hash] 同上
    [emoji] 随机字符串

    说明:[hash:8] 8表示截取前8位。

    /**
     * 生产环境配置
     */
    const MiniCssExtractPulgin = require('mini-css-extract-plugin');
    
    module.exports={
        entry:"./src/app.js",
        output:{
            filename:"bundle_[chunkhash:8].js",
            path:__dirname+"/dist"
        },
        mode:"production",
        module:{
            rules:[
                {
                    test:/.js$/,
                    use:'babel-loader'
                },
                {
                    test:/.less$/,
                    use:[
                        MiniCssExtractPulgin.loader,/*注意,这个loader时插件提供的*/
                        'css-loader',
                        'less-loader'
                    ]
                },
                {
                    test:/.(png|jpg)$/,
                    use:[
                        {
                            loader:'file-loader',
                            options:{
                                name:'./img/[name]_[hash:8].[ext]'
                            }
                        }
                    ]
                }
            ]
        },
        plugins:[
            new MiniCssExtractPulgin({
                filename:'[name]_[contenthash:8].css'
            })
        ]
    }
    

    文件压缩

    ​ 文件压缩是将打包后的html、css、js文件进行压缩。

    JS压缩

    ​ 使用UglifyjsWebpackPlugin这个插件进行压缩,webpack4生成环境下默认是开启的所以不需要配置。

    CSS压缩

    ​ 需要OptimizeCssAssetsWebpackPlugin插件

    ​ 需要cssnanoCSS压缩加载器(核心)

    # 安装依赖
    npm i -D optimize-css-assets-webpack-plugin cssnano
    
    //webpack.config.js
    /**
     * 生产环境配置
     */
    const MiniCssExtractPulgin = require('mini-css-extract-plugin');
    const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
    
    module.exports={
        entry:"./src/app.js",
        output:{
            filename:"bundle_[chunkhash:8].js",
            path:__dirname+"/dist"
        },
        mode:"production",
        module:{
            rules:[
                {
                    test:/.js$/,
                    use:'babel-loader'
                },
                {
                    test:/.less$/,
                    use:[
                        MiniCssExtractPulgin.loader,
                        'css-loader',
                        'less-loader'
                    ]
                },
                {
                    test:/.(png|jpg)$/,
                    use:[
                        {
                            loader:'file-loader',
                            options:{
                                name:'./img/[name]_[hash:8].[ext]'
                            }
                        }
                    ]
                }
            ]
        },
        plugins:[
            new MiniCssExtractPulgin({
                filename:'[name]_[contenthash:8].css'
            }),
            new OptimizeCssAssetsWebpackPlugin({
                /*作用于打包后的文件*/
                assetNameRegExp:/.css$/g,
                /*匹配打包后的文件*/
                cssProcessor:require('cssnano')
                /*使用cssnano压缩处理器*/
            })
            /*
                注意:是先有打包文件,才能进行压缩。
            */
        ]
    }  
    

    HTMlL压缩

    ​ 通过使用HtmlWebpackPlugin,设置参数进行压缩。

    html-webpack-plugin配置表:

    Name Type Default Description
    title {String} `` 用于生成的HTML文档的标题
    filename {String} 'index.html' 要写入HTML的文件。默认为“index . html”。您也可以在这里指定子目录 (eg: assets/admin.html)
    template {String} `` webpack 需要模板的路径。Please see the docs for details
    templateParameters {Boolean|Object|Function} `` 允许覆盖模板中使用的参数。
    inject {Boolean|String} true true || 'head' || 'body' || false 将所有资产注入给定的模板”或“templateContent”。当传递“true”或“body”时所有javascript资源都将放在body元素的底部。'head'`将脚本放在head元素中
    favicon {String} `` 将给定的favicon路径添加到输出HTML
    meta {Object} {} 允许注入“meta”标签。 E.g. meta: {viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'}
    minify {Boolean|Object} true 传递html-minifier的选项作为对象来缩小输出
    hash {Boolean} false 如果“true”,则在所有包含的脚本和CSS文件中附加一个惟一的“webpack”编译散列。这对于缓存破坏非常有用
    cache {Boolean} true 只有在文件被更改时才发出该文件
    showErrors {Boolean} true 错误细节将被写入HTML页面
    chunks {?} ? 允许您只添加一些块(e。g只是单元测试块)
    chunksSortMode {String|Function} auto 允许控制块在包含到HTML之前应该如何排序。允许的值是 'none' | 'auto' | 'dependency' | 'manual' | {Function}
    excludeChunks {Array.<string>} `` 允许你跳过一些块(e.g不要添加单元测试块)
    xhtml {Boolean} false 如果“true”将“link”标记呈现为自关闭(XHTML兼容)

    miniify配置表:

    默认情况下,大多数选项都是禁用的。

    Option Description Default
    caseSensitive 以区分大小写的方式处理属性(对自定义HTML标记很有用) false
    collapseBooleanAttributes 从布尔属性中省略属性值 false
    collapseInlineTagWhitespace 折叠时,不要在display:inline;元素之间留下任何空格。必须与collapseWhitespace = true一起使用 false
    collapseWhitespace 折叠有助于文档树中文本节点的空白 false
    conservativeCollapse 始终折叠到1个空格(永远不要完全删除)。必须与collapseWhitespace = true 一起使用FALSE
    continueOnParseError 处理解析错误 而不是流失。 false
    customAttrAssign 允许支持自定义属性赋值表达式的正则表达式数组(e.g. '<div flex?="{{mode != cover}}"></div>') [ ]
    customAttrCollapse 正则表达式,指定从中删除换行符的自定义属性 (e.g. /ng-class/)
    customAttrSurround 允许支持自定义属性环绕表达式的正则表达式数组 (e.g. <input {{#if value}}checked="checked"{{/if}}>) [ ]
    customEventAttributes 允许支持自定义事件属性的正则表达式数组minifyJS (e.g. ng-click) [ /^on[a-z]{3,}$/ ]
    decodeEntities 尽可能使用直接Unicode字符 false
    html5 根据HTML5规范解析 true
    ignoreCustomComments 一组正则表达式,允许在匹配时忽略某些注释 [ /^!/ ]
    ignoreCustomFragments 允许在匹配时忽略某些片段的正则表达式数组 (e.g. <?php ... ?>, {{ ... }}, etc.) [ /<%[\s\S]*?%>/, /<\?[\s\S]*?\?>/ ]
    includeAutoGeneratedTags 插入HTML解析器生成的标签 true
    keepClosingSlash 在单例元素上保留尾部斜杠 false
    maxLineLength 指定最大行长度。压缩输出将在有效HTML分割点处按换行符分割
    minifyCSS 在样式元素和样式属性中缩小CSS (uses clean-css) false (可能 true, Object, Function(text, type))
    minifyJS 缩小脚本元素和事件属性中的JavaScript(使用 UglifyJS) false (could be true, Object, Function(text, inline))
    minifyURLs 缩小各种属性中的URL(uses relateurl) false (could be String, Object, Function(text))
    preserveLineBreaks 当标记之间的空格包含换行符时,始终折叠为1换行符(从不完全删除它)。必须与collapseWhitespace = true一起使用 false
    preventAttributesEscaping 防止转义属性值 false
    processConditionalComments 通过minifier处理条件注释的内容 false
    processScripts 与通过缩小器处理的脚本元素类型相对应的字符串数组(例如text/ng-template, text/x-handlebars-template, etc.) [ ]
    quoteCharacter 用于属性值的引用类型(
    removeAttributeQuotes 尽可能删除属性周围的引号 false
    removeComments 剥离HTML注释 false
    removeEmptyAttributes 使用仅限空格的值删除所有属性 false (could be true, Function(attrName, tag))
    removeEmptyElements 删除所有带空内容的元素 false
    removeOptionalTags 删除可选标签 false
    removeRedundantAttributes 值匹配默认值时删除属性. false
    removeScriptTypeAttributes script标签中删除type =“text /javascript”。其他type属性值保持不变false
    removeStyleLinkTypeAttributes stylelink标签中删除type =“text /css”。其他type属性值保持不变false
    removeTagWhitespace 尽可能删除属性之间的空间。 请注意,这将导致HTML无效! FALSE
    sortAttributes 按频率对属性排序 false
    sortClassName 按频率对样式类进行排序 false
    trimCustomFragments 修剪ignoreCustomFragments周围的空白区域。 false
    useShortDoctype 用短(HTML5)doctype替换doctype false
    //webpack.config.js
    /**
     * 生产环境配置
     */
    const MiniCssExtractPulgin = require('mini-css-extract-plugin');
    const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const path = require('path');
    
    module.exports={
        entry:{index:"./src/app.js"},
        output:{
            filename:"bundle_[chunkhash:8].js",
            path:__dirname+"/dist"
        },
        mode:"production",
        module:{
            rules:[
                {
                    test:/.js$/,
                    use:'babel-loader'
                },
                {
                    test:/.less$/,
                    use:[
                        MiniCssExtractPulgin.loader,
                        'css-loader',
                        'less-loader'
                    ]
                },
                {
                    test:/.(png|jpg)$/,
                    use:[
                        {
                            loader:'file-loader',
                            options:{
                                name:'./img/[name]_[hash:8].[ext]'
                            }
                        }
                    ]
                }
            ]
        },
        plugins:[
            new MiniCssExtractPulgin({
                filename:'[name]_[contenthash:8].css'
            }),
            new OptimizeCssAssetsWebpackPlugin({
                assetNameRegExp:/.css$/g,
                cssProcessor:require('cssnano')
            }),
            new HtmlWebpackPlugin({
                title:'webpack学习',
                template:path.join(__dirname,'src/index.html'),
                filename:'index.html',
                chunks:['index'],
                /**
                 * 这里需要注意一下,如果entry写法是这样的:{index:'src/index.js'}那这里就需要使用chunks:['index']
                 * 如果entry写法是: 'src/index.js' 那这里就不需要使用chunks
                 * 
                 * 如果不按照上面的规定,下面的inject:true将不会生效
                 */
                inject:true,
                /**自动注入js与css */
                minify:{
                    html5:true,
                    collapseWhitespace:true,
                    preserveLineBreaks:false,
                    minifyCSS:true,
                    minifyJS:true,
                    removeComments:false
                }
            })
        ]
    }
    

    结束

    到这里webpack的基础用法已经写完了,接下来我会继续更新,webpack的进阶用法。

    如果你感觉我的文章对你有用,你可以点下面的大拇指给我鼓励,谢谢。

    如果想要转载,请标明出处

    相关文章

      网友评论

        本文标题:Webpack4 快速上手

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