webpack 4.x一起学习(二)

接着上一块https://juejin.im/post/5be29710e51d457e90193cf3

模块:CSS文件打包

Webpack在生产环境中有一个重要的作用就是减少http的请求数,就是把多个文件打包到一个js里,这样请求数就可以减少好多。在学习CSS打包之前,需要先对webpack.config.js里的Loaders配置项进行了解。

Loaders(以下所有的配置都是基于3版本的 如果过程中有bug 会进行改进)

Loaders是Webpack最重要的功能之一,他也是Webpack如此盛行的原因。通过使用不同的Loader,Webpack可以的脚本和工具,从而对不同的文件格式进行特定处理。

简单的举几个Loaders使用例子:

可以把SASS文件的写法转换成CSS,而不在使用其他转换工具。
可以把ES6或者ES7的代码,转换成大多浏览器兼容的JS代码。
可以把React中的JSX转换成JavaScript代码。

注意:所有的Loaders都需要在npm中单独进行安装,并在webpack.config.js里进行配置。下面我们对Loaders的配置型简单梳理一下。

test:用于匹配处理文件的扩展名的表达式,这个选项是必须进行配置的;
use:loader名称,就是你要使用模块的名称,这个选项也必须进行配置,否则报错;
include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
query:为loaders提供额外的设置选项(可选)。

打包CSS文件

建立index.css文件 ./src/css/index.css

要打包CSS你必须先要有个CSS文件,在/src目录下,我们建立一个css文件夹,在文件夹里建立index.css文件。代码内容如下

    body{
        background-color: red;  可以跟我不一样 完全为了测试
        color: white;
    }

CSS文件建立好后,需要引入到入口文件中,才可以打包到,这里我们引入到entry.js中。

/src/entery.js中在首行加入代码:
import css from './css/index.css';

也就是在entry.js中顶部导入

    import  css from './css/index.css';

    document.getElementById('title').innerHTML='Hello Webpack';

CSS和引入做好后,我们就需要使用loader来解析CSS文件了,这里我们需要两个解析用的loader,分别是style-loader和css-loader

首先我们先使用npm 安装(有些脚手架生成的webpack 会自动安装这些简单的加载器)

npm install style-loader css-loader --save-dev 一步到位

安装好之后查看一下package.json

两个loader都下载安装好后,我们就可以配置我们loaders了。

loaders配置:

修改webpack.config.js中module属性中的配置代码如下:

webpack.config.js

    const path = require('path')
    module.exports={
        mode: 'development',
        //入口文件的配置项
        entry:{
            //里面的entery是可以随便写的
            entry:'./src/entry.js',
        },
        //出口文件的配置项
        output:{
            //打包的路径文职
            path:path.resolve(__dirname,'dist'),
            //打包的文件名称
            filename:'bundle.js'
                    },
        //模块:例如解读CSS,图片如何转换,压缩
        module:{
            rules: [  =>以前此处是loaders 现在是rules
                {
                test: /\.css$/, =>正则 这个好理解
                use: [ 'style-loader', 'css-loader' ] =>使用css 与 style loader 来加载匹配到的css文件
                }
            ]
        },
        //插件,用于生产模版和各项功能
        plugins:[],
        //配置webpack开发服务功能
        devServer:{              
            host:'localhost',   //服务器的ip地址
            port:1573,  //端口
        }
    }

webpack一下,之前我们在js中引入了css 运行一下html ok 有样式了

友情提示:小伙伴们在测试的时候,可能会遇到找不到模块的 这种error 建议重新新建配置 重新npm插件 刚才我就莫名其妙找不到模块了 重新安装了一下就可以了

loader的三种写法:

有些小伙伴看到别人的CSS打包的写法和我的写法不太一样,是不是我写错了,loader还有几种写法,这里我们就看两种另外的写法。

使用use

    module:{
        rules:[
            {
                test:/\.css$/,
                use:['style-loader','css-loader']
            }
        ]
    },

把use换成loader。

    module:{
        rules:[
            {
                test:/\.css$/,
                loader:['style-loader','css-loader']
            }
        ]
    },

第三种写法:用use+loader的写法:

    module:{
        rules:[
            {
                test:/\.css$/,
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader"
                    }
                ]
            }
        ]
    },

没有全测 也不知道哪里需要修改 小伙伴可以自行测试一下

接下来我们来试着压缩一下js

在Webpack中可以很轻松的实现JS代码的压缩,它是通过插件的方式实现的,这里我们就先来引入一个uglifyjs-webpack-plugin(JS压缩插件,简称uglify)。

注意:虽然uglifyjs是插件,但是webpack版本里默认已经集成,不需要再次安装。

    const path = require('path')
    const webpack =require('webpack')  =>注意这里我们引入了webpack
    module.exports={
        mode: 'development',
        //入口文件的配置项
        entry:{
            //里面的entery是可以随便写的
            entry:'./src/entry.js',
        },
        //出口文件的配置项
        output:{
            //打包的路径文职
            path:path.resolve(__dirname,'dist'),
            //打包的文件名称
            filename:'bundle.js'
                    },
        //模块:例如解读CSS,图片如何转换,压缩
        module:{
            rules: [
                {
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
                }
            ]
        },
        //插件,用于生产模版和各项功能
        plugins:[
            new webpack.optimize.UglifyJsPlugin() =>因为是webpack集成的 所以要在上方引入webpack
        ]            
     
    }

此时我们webpack一下 你会发现 报错(报错的内容就不截屏了)

在webpack4.0版本中已经废弃了之前 UglifyJsPlugin的用法,用的是optimization.minimize

重新配置一下webpack

    const path = require('path') 
                                                     删除了webpack模块引入

    const UglifyJsPlugin=require('uglifyjs-webpack-plugin');=>需要 npm 手动安装
    module.exports={
        mode: 'development',
        //入口文件的配置项
        entry:{
            //里面的entery是可以随便写的
            entry:'./src/entry.js',
        },
        //出口文件的配置项
        output:{
            //打包的路径文职
            path:path.resolve(__dirname,'dist'),
            //打包的文件名称
            filename:'bundle.js'
                    },
        //模块:例如解读CSS,图片如何转换,压缩
        module:{
            rules: [
                {
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
                }
            ]
        },
        //插件,用于生产模版和各项功能
        plugins:[
            
        ],
        
        optimization: {
            minimizer: [
                new UglifyJsPlugin({
                    uglifyOptions: {
                        compress: false
                    }
                })
            ]
        },
        
     
    }

这里需要注意一下 webpack打包也是分模式的 默认是mode ‘production(生产环境)’

如果我们没在config.js中标明webpack 的mode 直接webpack是会有警告的

就是说我们打包的命令完整应该是 webpack --mode production/development

默认是production 此方法打包文件会小很多 注意一下即可

production 其实默认自带了uglifyjs-webpack-plugin 插件 已经不需要使用

也就是我们在production 状态下 其实可以不需要配置 直接 webpack --mode development 即可

接下来我还是设置默认 production 环境下测试 方便点

插件配置:HTML文件的发布

webpack 构建项目时, 通过指定的入口文件,会将所有的js css 等以依赖模块的形式打包成一个或多个的脚本文件,通常情况下,脚本文件会附属于html 文件运行,这时候需要将 打包好的脚本文件,注入到html 中, html-webpack-plugin 插件的目的是, 以一个html 为模板, 将打包好的脚本注入到模板中, 相关的配置如下

先安装 html-webpack-plugin
npm i html-webpack-plugin -D

安装好之后 我们在plugins中配置

    const path = require('path')
    const htmlPlugin = require('html-webpack-plugin');  =>引入模块
    module.exports={

        //入口文件的配置项
        entry:{
            //里面的entery是可以随便写的
            entry:'./src/entry.js',
        },
        //出口文件的配置项
        output:{
            //打包的路径文职
            path:path.resolve(__dirname,'dist'),
            //打包的文件名称
            filename:'bundle.js'
        },
        //模块:例如解读CSS,图片如何转换,压缩
        module:{
            rules: [
                {
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
                }
            ]
        },
        //插件,用于生产模版和各项功能
        plugins:[
            new htmlPlugin({   =>这是一般情况下的配置  打包html 
                minify:{
                    removeAttributeQuotes:true
                },
                hash:true,
                template:'./src/index.html'
            })
        ],                                 
    }

minify:是对html文件进行压缩
hash:为了开发中js有缓存效果,所以加入hash,这样可以有效避免缓存JS。
template:是要打包的html模版路径和文件名称。

此时我们webpack --mode production

此时dist下生成了 index.html js是上面的命令生成的 这就是我们常见的状态了 熟悉vue的小伙伴都知道 npm run build就会生成这俩文件 此时我们直接开index.html 也是有效果的 如果需要改名的话可以再配置一个参数 filename:‘filename.html’ 一定要加后缀

图片迈坑:CSS中的图片处理

在学习Webapck过程中你可能遇到的第一个坑就是CSS中的图片处理。很多webpack新手都在图片的坑中无法自拔(有的小伙伴在开发环境中是可以找到图片的,但是一打包后就找不到图片了,有的小伙伴是不知道如何正确引入html或者css中的图片,导致程序出错)

图片写入css 我们先找张图片先 http://img1.imgtn.bdimg.com/it/u=198855387,108109132&fm=26&gp=0.jpg

注意一定要本地图片啊 刚才偷懒使用网络图片发现居然成功了 不能成功 一定要失败的

index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>webpack</title>
    </head>
    <body>
        <div id="tupian"></div>
        <script src="./../dist/bundle.js"></script>
    </body>
    </html>

index.css css还是在js中引入

#tupian{
background-image: url('./../image/1.jpg');
width:466px;
height:453px;
 }

我们这时候 通过webpack --mode production 是会失败的 失败的原因就是缺少loader的解析

对于图片我们也需要安装两loader

安装file-loader和url-loade
npm install --save-dev file-loader url-loader

file-loader:解决引用路径的问题,拿background样式用url引入背景图来说,我们都知道,webpack最终会将各个模块打包成一个文件,因此我们样式中的url路径是相对入口html页面的,而不是相对于原始css文件所在的路径的。这就会导致图片引入失败。这个问题是用file-loader解决的,file-loader可以解析项目中的url引入(不仅限于css),根据我们的配置,将图片拷贝到相应的路径,再根据我们的配置,修改打包后文件引用路径,使之指向正确的文件。

url-loader:如果图片较多,会发很多http请求,会降低页面性能。这个问题可以通过url-loader解决。url-loader会将引入的图片编码,生成dataURl。相当于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了。当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的还会使用file-loader进行copy。

安装好之后我们来配置webpack 直接在module中配置loader

    const path = require('path')
    const htmlPlugin = require('html-webpack-plugin');
    module.exports={

        //入口文件的配置项
        entry:{
            //里面的entery是可以随便写的
            entry:'./src/entry.js',
        },
        //出口文件的配置项
        output:{
            //打包的路径文职
            path:path.resolve(__dirname,'dist'),
            //打包的文件名称
            filename:'bundle.js'
        },
        //模块:例如解读CSS,图片如何转换,压缩
        module:{
            rules: [
                {
                test: /\.css$/,  => css的loader
                use: [ 'style-loader', 'css-loader' ]  =>这边顺带提一下 其实webpack的loader是从右往左看
                                                 =>也就是 先使用css loader  再使用style loader  
                },
                {
                    test:/\.(png|jpg|gif)/ , =>图片的loader
                    use:[{
                        loader:'url-loader',
                        options:{
                            limit:500000   =>不认识limit的小伙伴可以自行百度一下  类似我们的流量 哈哈  好吧其实就是指500000B
                        }
                    }]
                 }
            ]
        },
        //插件,用于生产模版和各项功能
        plugins:[
            new htmlPlugin({
                minify:{
                    removeAttributeQuotes:true
                },
                hash:true,
                template:'./src/index.html'
            })
        ],
            
    }

接下来我们webpack --mode production 即可 成功生成

为什么只使用了url-loader

有的小伙伴会发现我们并没有在webpack.config.js中使用file-loader,但是依然打包成功了。我们需要了解file-loader和url-loader的关系。url-loader和file-loader是什么关系呢?简答地说,url-loader封装了file-loader。url-loader不依赖于file-loader,即使用url-loader时,只需要安装url-loader即可,不需要安装file-loader,因为url-loader内置了file-loader。通过上面的介绍,我们可以看到,url-loader工作分两种情况:

1.文件大小小于limit参数,url-loader将会把文件转为DataURL(Base64格式);

2.文件大小大于limit,url-loader会调用file-loader进行处理,参数也会直接传给file-loader。

也就是说,其实我们只安装一个url-loader就可以了。但是为了以后的操作方便,我们这里就顺便安装上file-loader。

###图片迈坑:CSS分离与图片路径处理

CSS分离:extract-text-webpack-plugin

有些简单的交互页面中,你的JavasScript页面代码会非常少,而大部分代码都在CSS中,这时候项目组长会要求把CSS单独提取出来,方便以后更改。遇到这个需求你不要惊慌,已经有大神为我们准备好了对象的插件(plugin)

这个插件就可以完美的解决我们提取CSS的需求,但是webpack官方其实并不建议这样作,他们认为CSS就应该打包到JavasScript当中以减少http的请求数。但现实中的需求往往不是我们前端能控制的,有些需求是我们不能控制的,分离CSS就是这样一个既合理由不合理的需求,说白了,还是得听老大的 ,如果小姐姐让你这样你做不做呢?

npm install --save-dev extract-text-webpack-plugin

安装好了自然要用 我们直接在webpack上方 引入 const extractTextPlugin = require("extract-text-webpack-plugin")

引入之后 我们只需在webpack中new 使用 并且还要配置关于css的加载器

      const path = require('path')
      const htmlPlugin = require('html-webpack-plugin');
      const extractTextPlugin = require("extract-text-webpack-plugin")
      module.exports={
        //入口文件的配置项
        entry:{
            //里面的entery是可以随便写的
            entry:'./src/entry.js',
        },
        //出口文件的配置项
        output:{
            //打包的路径位置
            path:path.resolve(__dirname,'dist'),
            //打包的文件名称
            filename:'bundle.js'
        },
        //模块:例如解读CSS,图片如何转换,压缩
        module:{
            rules: [
                {
                // test: /\.css$/,
                // use: [ 'style-loader', 'css-loader' ]
                test: /\.css$/,
                use: extractTextPlugin.extract({
                  fallback: "style-loader",
                  use: "css-loader"
                })
                },
                {
                    test:/\.(png|jpg|gif)/ ,
                    use:[{
                        loader:'url-loader',
                        options:{
                            limit:500000
                        }
                    }]
                 }
            ]
        },
        //插件,用于生产模版和各项功能
        plugins:[
            new htmlPlugin({
                minify:{
                    removeAttributeQuotes:true
                },
                hash:true,
                template:'./src/index.html'
            }),
            new extractTextPlugin("/css/index.css") =>注意插件的使用   (此处是生成的文件位置  前面配置了path 默认都是dist文件下的)
        ],

    }

此时我们webpack一下 是有错误的 因为extract-text-webpack-plugin 不支持4版本以上的
我们既然学习4版本的webpack肯定不能降级 好 我们升级
npm install --save-dev [email protected]

安装好之后 其余不变 再次 webpack一下 因为此时生成打包了三个文件 我给截图一下

这样就成功分离了 本来是起初我们导入js中的 此时成功生成了index.css 并且里面的url是base64形式的,但是我们此时浏览dist下的html是没有东西的 因为我们路径有问题 这里是指图片路径 不是文件路径

图片路径问题

利用extract-text-webpack-plugin插件很轻松的就把CSS文件分离了出来,但是CSS路径并不正确,很多小伙伴就在这里搞个几天还是没有头绪,网上也给出了很多的解决方案,我觉的最好的解决方案是使用publicPath解决

publicPath:是在webpack.config.js文件的output选项中,主要作用就是处理静态文件路径的。

此处增加一个知识 webpack-dev-server 本来是不想配置后面给大家简单提一下,毕竟单独测试webpack的真的不多,很多时候都是看webpack或者脚手架生成直接修改

测试publicPath的时候 没设置服务器状态老报错 使用live-server也不好配置 所以简单提一下webpack-dev-server的配置

npm install webpack-dev-server –save-dev 先安装

在webpack.config.js 中配置

        plugins:[
            new htmlPlugin({
                minify:{
                    removeAttributeQuotes:true
                },
                hash:true,
                template:'./src/index.html'
            }),
            new extractTextPlugin("/css/index.css")
        ],
        devServer:{  =>注意 与plugins同级
            //设置基本目录结构
            contentBase:path.join(__dirname,'dist'),
            //服务器的IP地址,可以使用IP也可以使用localhost
           //  不知道自己IP的可以 打开cmd 输入ipconfig 查看
            host:'localhost',
            //服务端压缩是否开启
            compress:true,
            //配置服务端口号
            port:1717
        }

在packge.json的 scripts 中输入"dev": "webpack-dev-server --open"

我们启动webpack-dev-server的时候只需要npm run dev 即可

启动webpack-dev-server之后 会启动热更新 当我们改变内容保存的时候会自动进行webpack命令打包 实时更新内容

别忘了我们主要的目的 ,解决图片路径问题 使用publicPath

主要看output模块

    const path = require('path')
    const htmlPlugin = require('html-webpack-plugin');
    const extractTextPlugin = require("extract-text-webpack-plugin")
    module.exports={
       // mode:'development',
        //入口文件的配置项
        entry:{
            //里面的entery是可以随便写的
            entry:'./src/entry.js',
        },
        //出口文件的配置项
        output:{
            //打包的路径文职
            path:path.resolve(__dirname,'dist'),
            //打包的文件名称
            filename:'bundle.js',
            publicPath:'localhost:1717'  
        },
        //模块:例如解读CSS,图片如何转换,压缩
        module:{
            rules: [
                {
                // test: /\.css$/,
                // use: [ 'style-loader', 'css-loader' ]
                test: /\.css$/,
                use: extractTextPlugin.extract({
                  fallback: "style-loader",
                  use: "css-loader"
                })
                },
                {
                    test:/\.(png|jpg|gif)/ ,
                    use:[{
                        loader:'url-loader',
                        options:{
                            limit:500000
                        }
                    }]
                 }
            ]
        },
        //插件,用于生产模版和各项功能
        plugins:[
            new htmlPlugin({
                minify:{
                    removeAttributeQuotes:true
                },
                hash:true,
                template:'./src/index.html'
            }),
            new extractTextPlugin("/css/index.css")
        ],
        devServer:{
            //设置基本目录结构
            contentBase:path.resolve(__dirname,'dist'),
            //服务器的IP地址,可以使用IP也可以使用localhost
            host:'localhost',
            //服务端压缩是否开启
            compress:true,
            //配置服务端口号
            port:1717
        }

    }

接着我们打包之后 即可显示图片了

猜你喜欢

转载自blog.csdn.net/qq_26006661/article/details/83826088