美文网首页
Webpack 3.X

Webpack 3.X

作者: greenteaObject | 来源:发表于2017-11-13 18:02 被阅读0次

    Webpack的作用

    • 打包:可以把多个Javascript文件打包成一个文件,减少服务器压力和下载带宽。
    • 转换:把拓展语言转换成为普通的JavaScript,让浏览器顺利运行。
    • 优化:前端变的越来越复杂后,性能也会遇到问题,而WebPack也开始肩负起了优化和提升性能的责任。

    图例:


    image.png

    安装

    前提是你已经安装node

    //全局安装webpack
    npm install -g webpack
    //初始化
    npm init
    //项目目录安装webpack
    npm install webpack --save-dev
    

    全局安装并不推荐,因为在使用不同的webpack项目中,可能会导致构建失败

    什么是开发环境和生产环境?
    • 开发环境:开发时需要的环境,这里指在开发时需要依赖的包
    • 生产环境:程序开发完成,开始运行后的环境,这里指要使项目运行,所需要的依赖包

    一个DEMO

    webpack {entry file} {destination for bundled file}
    
    webpack src/entry.js dist/bundle.js
    

    配置文件 : 入口和出口

    module.exports={
        //入口文件的配置项
        entry:{},
        //出口文件的配置项
        output:{},
        //模块:例如解读CSS,图片如何转换,压缩
        module:{},
        //插件,用于生产模版和各项功能
        plugins:[],
        //配置webpack开发服务功能
        devServer:{}
    }
    
    • entry:配置入口文件的地址,可以是单一入口,也可以是多入口。
    • output:配置出口文件的地址,在webpack2.X版本后,支持多出口配置。
    • module:配置模块,主要是解析CSS和图片转换压缩等功能。
    • plugins:配置插件,根据你的需要配置不同功能的插件。
    • devServer:配置开发服务功能
    //入口文件的配置项
    entry:{
        //里面的entry是可以随便写的
        entry:'./src/entry.js'
    },
    
    //出口文件的配置项
    output:{
        //打包的路径
        path:path.resolve(__dirname,'dist'),    //获取绝对路径
        //打包的文件名称
        filename:'bundle.js'
        
    }
    

    需要引入path

    const path = require('path');
    

    现在的webpack.config.js代码

    const path = require('path');
    module.exports={
        //入口文件的配置项
        entry:{
            entry:'./src/entry.js'
        },
        //出口文件的配置项
        output:{
            //输出的路径,用了Node语法
            path:path.resolve(__dirname,'dist'),
            //输出的文件名称
            filename:'bundle.js'
        },
        //模块:例如解读CSS,图片如何转换,压缩
        module:{},
        //插件,用于生产模版和各项功能
        plugins:[],
        //配置webpack开发服务功能
        devServer:{}
    }
    
    多入口,多出口
    const path = require('path');
    module.exports={
        //入口文件的配置项
        entry:{
            entry:'./src/entry.js',
            //这里我们又引入了一个入口文件
            entry2:'./src/entry2.js'
        },
        //出口文件的配置项
        output:{
            //输出的路径,用了Node语法
            path:path.resolve(__dirname,'dist'),
            //输出的文件名称
            filename:'[name].js'
        },
        //模块:例如解读CSS,图片如何转换,压缩
        module:{},
        //插件,用于生产模版和各项功能
        plugins:[],
        //配置webpack开发服务功能
        devServer:{}
    }
    

    [name]的意思是根据入口文件的名称,打包成相同的名称,有几个入口文件,就可以打包出几个文件。

    配置文件 : 服务和热更新

    设置webpack-dev-server

    先安装webpack-dev-server

    devServer:{
        //设置基本目录结构
        contentBase:path.resolve(__dirname,'dist'),
        //服务器的IP地址,可以使用IP也可以使用localhost
        host:'localhost',
        //服务端压缩是否开启
        compress:true,
        //配置服务端口号
        port:9898
    }
    
    • contentBase:配置服务器基本运行路径,用于找到程序打包地址。
    • host:服务运行地址,建议使用本机IP
    • compress:服务器端压缩选型,一般设置为开启
    • port:服务运行端口
    支持热更新

    在npm run server 启动后,它是有一种监控机制的(也叫watch)。它可以监控到我们修改源码,并立即在浏览器里给我们更新。

    //package.json
    "scripts": {
        "server":"webpack-dev-server"
     },
    

    打包CSS文件

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

    所有的Loaders都需要在npm中单独进行安装,并在webpack.config.js里进行配置。

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

    CSS文件建立好后,需要引入到入口文件中,才可以打包到

    /src/entry.js
    import css from './css/index.css';
    

    安装loader

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

    loaders配置

    //webpack.config.js
    module:{
        rules:[
            {
                test:/\.css$/,
                use:['style-loader','css-loader']
            }
        ]
    },
    
    loader的三种写法
    //use
    module:{
        rules:[
            {
                test:/\.css$/,
                use:['style-loader','css-loader']
            }
        ]
    },
    
    //loader
    module:{
        rules:[
            {
                test:/\.css$/,
                loader:['style-loader','css-loader']
            }
        ]
    },
    
    //use+loader
    module:{
        rules:[
            {
                test:/\.css$/,
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader"
                    }
                ]
            }
        ]
    },
    

    压缩JS代码

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

    //webpack.config.js
    //引入
    const uglify = require('uglifyjs-webpack-plugin');
    //配置插件
    plugins:[
        new uglify()
    ],
    

    现在的webpack.config.js

    const path=require('path');
    const uglify = require('uglifyjs-webpack-plugin');
    module.exports={
        entry:{
            entry:'./src/entry.js',
            entry2:'./src/entry2.js'
        },
        output:{
            path:path.resolve(__dirname,'dist'),
            filename:'[name].js'
        },
        module:{
            rules:[
                {
                    test:/\.css$/,
                    use: ["style-loader", "css-loader"]
                }
            ]
        },
        plugins:[
            new uglify()
        ],
        devServer:{
           contentBase:path.resolve(__dirname,'dist'),
           host:'192.168.0.104',
           compress:true,
           port:1717
        }
    }
    

    HTML文件的发布

    在之前,html文件应该是在src目录下的.


    image.png
    1. 先把html文件放入到src目录下
    2. 配置webpack.config.js文件,先引入html-webpack-plugin插件。
    const htmlPlugin= require('html-webpack-plugin');
    
    1. npm安装
    npm install --save-dev html-webpack-plugin
    
    1. webpack.config.js配置
    plugins:[
        new htmlPlugin({
            minify:{
                removeAttributeQuotes:true
            },
            hash:true,
            template:'./src/index.html'
        })
    ],
    
    • minify:是对html文件进行压缩,removeAttrubuteQuotes是却掉属性的双引号。
    • hash:为了开发中js有缓存效果,所以加入hash,这样可以有效避免缓存JS。
    • template:是要打包的html模版路径和文件名称。

    html文件的打包可以有效的区分开发目录和生产目录

    图片处理

    CSS中的图片处理

    1. css中写入一些图片的样式
    #tupian{
       background-image: url(../images/manhua.png);
       width:466px;
       height:453px;
    }
    
    1. 安装file-loader和url-loader
    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。

    1. 配置url-loader
    //webpack.config.js文件
    module:{
        rules:[
            {
                test:/\.css$/,
                use:['style-loader','css-loader']
            },
            {
                test:/\.(png|jpg|gif)$/,
                use:[{
                    loader:'url-loader',
                    options:{
                        limit:5000,
                        outputPath:'images/'
                    }
                }]
            }
        ]
    },
    
    • test:/.(png|jpg|gif)/是匹配图片文件后缀名称。
    • use:是指定使用的loader和loader的配置参数。
    • limit:是把小于5000B的文件打成Base64的格式,写入JS。
    • outputPath : 将图片放入指定的路径下
    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。

    CSS分离与图片路径处理

    CSS分离:extract-text-webpack-plugin
    1. 安装
    npm install --save-dev extract-text-webpack-plugin
    
    1. 引入
    const extractTextPlugin = require("extract-text-webpack-plugin");
    
    1. 设置plugins,只需要new一下这个对象就可以了
    new extractTextPlugin("css/index.css")
    
    1. 修改原来的style-loader和css-loader。
    module:{
        rules:[
            {
                test:/\.css$/,
                use: extractTextPlugin.extract({
                    fallback:"style-loader",
                    use:"css-loader"
                })
            },
            {
                test:/\.(png|jpg|gif)$/,
                use:[{
                    loader:'url-loader',
                    options:{
                        limit:5000,
                        outputPath:'images/'
                    }
                }]
            }
        ]
    },
    
    图片路径问题

    利用extract-text-webpack-plugin插件很轻松的就把CSS文件分离了出来,但是CSS路径并不正确,使用publicPath解决

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

    //webpack.config.js
    //声明一个对象
    var website ={
        publicPath:"http://192.168.1.108:1717/"
    }
    //引用这个对象的属性
    output : {
        path:path.resolve(__dirname,'dist'),
        filename: '[name].js',
        publicPath:website.publicPath
    },
    

    处理HTML中的图片

    html-withimg-loader
    1. 安装
    npm install html-withimg-loader --save-dev
    
    1. 配置loader
    //webpack.config.js
    {
        test: /\.(htm|html)$/i,
         use:[ 'html-withimg-loader'] 
    }
    

    CSS进阶

    打包Less

    1. 安装
    //安装less服务
    npm install less --save-dev
    //安装less-loader
    npm install less-loader --save-dev
    
    1. 写loader配置
    //webpack.config.js
    {
        test: /\.less$/,
        use: [{
               loader: "style-loader" // creates style nodes from JS strings
            }, {
                loader: "css-loader" // translates CSS into CommonJS
            , {
                loader: "less-loader" // compiles Less to CSS
            }]
    }
    
    1. 引入到入口文件中
    import less from './less/black.less';
    
    把less分离
    {
        test:/\.less$/,
        use:extractTextPlugin.extract({
            use:[{
                loader:"css-loader"
            },{
                loader:"less-loader"
            }],
            fallback:"style-loader"
        })
    }
    

    SASS的打包和分离

    和Less非常相似

    npm install node-sass sass-loader --save-dev
    
    //webpack.config.js
    {
        test:/\.scss$/,
        use:extractTextPlugin.extract({
            use:[{
                loader:"css-loader"
            },{
                loader:"sass-loader"
            }],
            fallback:"style-loader"
        })
    }
    

    postcss自动添加CSS属性前缀

    postcss
    1. 安装
    npm install postcss-loader autoprefixer --save-dev
    
    1. 在项目根目录(和webpack.config.js同级)建立postcss.config.js
    //postcss.config.js
    module.exports = {
        plugins: [
            require('autoprefixer')
        ]
    }
    
    1. 提取CSS的loader配置
    {
        test: /\.css$/,
        use: extractTextPlugin.extract({
            fallback: 'style-loader',
            use: [
                { loader: 'css-loader', options: { importLoaders: 1 } },
                'postcss-loader'
            ]
        })
        
    }
    

    消除未使用的CSS

    PurifyCSS-webpack
    1. 安装
      purifycss-webpack依赖于purify-css这个包
    npm i purifycss-webpack purify-css -D
    
    1. 引入glob和purifycss-webpack
      同步检查模板,引入node的glob对象使用
    //webpack.config.js
    const glob = require('glob');
    const purifyCssPlugin = require("purifycss-webpack");
    
    1. 配置plugins
      这里配置了一个paths,主要是需找html模板,purifycss根据这个配置会遍历你的文件,查找哪些css被使用了。
    //webpack.config.js
    plugins:[
        //new uglify() 
        new htmlPlugin({
            minify:{
                removeAttrubuteQuotes:true
            },
            hash:true,
            template:'./src/index.html'
            
        }),
        new extractTextPlugin("css/index.css"),
        new PurifyCSSPlugin({
            // Give paths to parse for rules. These should be absolute!
            paths: glob.sync(path.join(__dirname, 'src/*.html')),
            })
     
    ]
    

    使用这个插件必须配合extract-text-webpack-plugin这个插件

    给webpack增加babel支持

    Babel

    Babel其实是一个编译JavaScript的平台,它的强大之处表现在可以通过便宜帮你达到以下目的:

    • 使用下一代的javaScript代码(ES6,ES7….),即使这些标准目前并未被当前的浏览器完全支持。
    • 使用基于JavaScript进行了扩展的语言,比如React的JSX。

    Babel的安装与配置

    Babel其实是几个模块化的包,其核心功能位于称为babel-core的npm包中,webpack可以把其不同的包整合在一起使用,对于每一个你需要的功能或拓展,你都需要安装单独的包(用得最多的是解析ES6的babel-preset-es2015包和解析JSX的babel-preset-react包)。

    1. 安装
    npm i babel-core babel-loader babel-preset-env -D
    
    1. 在webpack中配置Babel的方法
    {
        test:/\.(jsx|js)$/,
        use:{
            loader:'babel-loader',
            options:{
                presets:[
                    "env"
                ]
            }
        },
        exclude:/node_modules/
    }
    

    现在打包的代码就是经过处理的了

    .babelrc

    虽然Babel可以直接在webpack.config.js中进行配置,但是考虑到babel具有非常多的配置选项,如果写在webapck.config.js中会非常的雍长不可阅读,所以把配置写在.babelrc文件里。

    1. 在项目根目录新建.babelrc文件,并把配置写到文件里。
    //.babelrc
    {
        "presets":["env"]
    }
    
    1. webpack.config.js里的loader配置
    {
        test:/\.js$/,
        use:{
            loader:'babel-loader',
        },
        exclude:/node_modules/
    }
    

    打包后的代码调试

    使用了webpack后,所以代码都打包到了一起,给调试带来了麻烦,但是webpack已经为我们充分考虑好了这点,它支持生产Source Maps来方便我们的调试。在使用webpack时只要通过简单的devtool配置,webapck就会自动给我们生产source maps 文件,map文件是一种对应编译文件和源文件的方法,让我们调试起来更简单。

    在配置devtool时,webpack给我们提供了四种选项。

    • source-map:在一个单独文件中产生一个完整且功能完全的文件。这个文件具有最好的source map,但是它会减慢打包速度;
    • cheap-module-source-map:在一个单独的文件中产生一个不带列映射的map,不带列映射提高了打包速度,但是也使得浏览器开发者工具只能对应到具体的行,不能对应到具体的列(符号),会对调试造成不便。
    • eval-source-map:使用eval打包源文件模块,在同一个文件中生产干净的完整版的sourcemap,但是对打包后输出的JS文件的执行具有性能和安全的隐患。在开发阶段这是一个非常好的选项,在生产阶段则一定要不开启这个选项。
    • cheap-module-eval-source-map:这是在打包文件时最快的生产source map的方法,生产的 Source map 会和打包后的JavaScript文件同行显示,没有影射列,和eval-source-map选项具有相似的缺点。

    四种打包模式,有上到下打包速度越来越快,不过同时也具有越来越多的负面作用,较快的打包速度的后果就是对执行和调试有一定的影响。

    实战

    开发与生产并行设置

    1. 修改package.json命令
    "scripts": {
      "start": "set type=dev&webpack-dev-server",
      "build": "set type=build&webpack"
    },
    
    1. 修改webpack.config.js文件
    if(process.env.type== "dev"){
        var website={
            publicPath:"http://localhost:9898/"
        }
        console.log( encodeURIComponent(process.env.type) );
    }else{
        var website={
            publicPath:"http://www.guoqianchen.com/"
        }
        console.log( encodeURIComponent(process.env.type) );
    }
    
    1. MAC下的package.json配置
      MAC电脑下需要把set换成export,并且要多加一个&符
    "scripts": {
      "dev": "set type=dev&webpack-dev-server",
      "build": "set type=build&webpack",
      "dev_mac": "export type=dev&&webpack-dev-server",
      "build_mac": "export type=build&&webpack"
    },
    

    模块化

    webpack.config.js要使用Common.js方式引入

    打包第三方类库

    引入jQuery
    1. 安装jquery
    npm install jquery --save
    
    1. 引入到JS文件中
    import $ from 'jquery'
    
    用plugin引入

    ProvidePlugin是一个webpack自带的插件,Provide的意思就是装备、提供。因为ProvidePlugin是webpack自带的插件,所以要先再webpack.config.js中引入webpack。

    1. webpack.config.js中引入webpack
    const webpack = require('webpack');
    

    在webpack.config.js里引入必须使用require,否则会报错的,这点小伙伴们一定要注意。

    2.配置plugin模块

    plugins:[
        new webpack.ProvidePlugin({
            $:"jquery"
        })
    ],
    

    配置好后,就可以在你的入口文件中使用了,而不用再次引入了。这是一种全局的引入,在实际工作中也可以很好的规范项目所使用的第三方库。

    watch的配置

    watchOptions:{
        //检测修改的时间,以毫秒为单位
        poll:1000, 
        //防止重复保存而发生重复编译错误。这里设置的500是半秒内重复保存,不进行打包操作
        aggregeateTimeout:500, 
        //不监听的目录
        ignored:/node_modules/, 
    }
    
    webpack --watch
    

    BannerPlugin插件

    1. 配置plugins
    new webpack.BannerPlugin('hello')
    

    在使用这个插件之前必须引入webpack。

    const webpack = require('webpack');
    

    相关文章

      网友评论

          本文标题:Webpack 3.X

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