webpack

作者: Liberty寒风 | 来源:发表于2017-03-31 10:47 被阅读0次

    什么是webpack

    webpack是一个模块打包的解决方案

    webpack和gulp对比

    其实没啥可比性,gulp是构建前端自动化流程的工具,而webpack只是一个模块打包的。gulp可以制定一些任务,自动执行一些操作。webpack是通过一个给定的入口主文件,然后将这个主文件内的所有依赖的文件都用loaders处理,最后打包成一个浏览器可以识别的js文件。webpack的处理速度更快,它把所有文件都当做模块处理,css以及图片等等。

    基础的配置文件

    module.exports = {
      context:__dirname+"/app"
      entry:  "./main.js",//唯一入口文件
      output: {
        path: __dirname + "/public",//打包后的文件存放的地方,相对
        filename: "bundle.js"//打包后输出文件的文件名
        //publicPath:'http://cdn' 一般通过比如cdn加载网络静态资源,作为前缀路径,一般生产环境会用这个替换路径
      }
    }
    

    注意,“__dirname”是node.js中的一个全局变量,它指向当前执行脚本所在的目录。

    当entry为数组或对象

    当有多个入口vendor和index的时候,会分别从多个入口内进入,并扫描全部依赖生成一个vendor.js和index.js文件

    module.exports = {
      entry:{
        "vendor":['jquery','abc.js'],
        "index":'./public/src/index.js',
      },
      output:{
        path:'/public',
        filename:"[name].js" //vendor.js,index.js
      }
    }
    

    更快捷的执行打包

    有时候我们需要执行webpack —watch —xxx-xx等一系列很长的命令时,这样去敲是不太方便的,我们可以将长命令配置在package.json中,通过npm脚本执行。

    {
      "name": "webpack_demo",
      "version": "1.0.0",
      "description": "webpack_demo",
      "scripts": {
        "abc": "webpack xxx xxx xxx" //在此处配置,相当于把npm run abc替换成了webpack xxx
      },
    }
    

    Source Maps方便调试

    打包后文件出错往往找不到对应的源代码位置,Source Maps就是用来解决这个问题的,他可以帮我们映射编译文件对应源文件的位置。

    module.exports = {
      // 注意,source map有多种,下面这种是比较合适的
      devtool:'eval-source-map',//配置生成Source Maps,
      entry:__dirname + "/app/main.js",
      output:{
        path:__dirname + "/public",
        filename:"bundle.js"
      }
    }
    

    webpack构建本地服务器

    通过安装webpack-dev-server的模块,然后配置devserver来开启本地服务器,它可以让浏览器检测代码修改,并自动刷新页面显示修改后的结果,它是基于node.js构建的。

    module.exports = {
      devServer:{
        contentBase:"./public", //本地服务器所加载的页面所在的目录
        colors:true, //终端中输出结果为彩色
        historyApiFallback:true, //不跳转
        inline:true //实时刷新
      }
    }
    

    resolve

    用来控制搜索路径,平常引用文件的时候路径比较长,比如./app/src/components,现在我们可以用一个别名代替

    module.exports = {
      resolve:{
        //默认从此处开始搜索模块
        root:[ 
          path.join(__dirname,"node_modules")
        ],
        //别名
        alias:{ 
          js:path.join(_dirname,"../app/src/scripts")
        },
        //扩展文件名后缀,require模块的时候可以不写后缀名
        extensions: ['', '.js', '.vue', '.scss', '.css']
      }
    }
    

    现在引用文件只需要js/xxx.js就可以了

    按需加载模块

    通过require.ensure声明的文件,会被按需加载,所以这些文件必须是一个独立的个体,在需要被展示的时候才动态加载。一般路由组件的场景很多。

    // 定义一个FirstPage的懒加载组件
    let FirstPage = (location,cb) => {
      require.ensure([],require => {
        cb(null,require('../containner/xxx.js').default)//export default暴露的时候需要加一个default
      },FirstPage)
    }
    
    // 在webpack的output中进行相应的配置
    module.exports = {
      output:{
        path:__dirname + '/public/',
        filename:'[name][hash].js',
        chunkFilename:'[name].chunk.[hash].js',//单个文件名
        sourceMapFilename: 'js/[name].js.map',//独立文件sourcemap
      }
    }
    

    注意:这里[name]会被块名替换掉,[hash]会被编译的hash替换掉,其他同理。

    Loaders

    webpack中的核心应该就是loaders了,通过不同的loader来打包处理不同的文件,比如说将es6、es7转换成浏览器识别的样子。

    loader模块需要单独安装,并且在modules下进行配置:

    • test:匹配一个被loader处理的文件的拓展名的正则表达式
    • loader:loader的名称
    • include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)
    • query:为loaders提供额外的设置选项()
    module.exports = {
      module:{
        rules:[ // loaders数组,里面放的都是loader
          {
            test:/\.json$/,
            use:[{ //注意,webpack1和webpack2的loader语法不太一样
              loader:"json-loader",
              options:{xxx:"xxx",aaa:'aaa'}//向json-loader上配置参数。
              //loader:"json?xxx=xxx&aaa=aaa" //还可以这样配置参数
            }]
          }
        ]
      }
    }
    

    Babel

    babel是一个比较复杂的loader,它可以编译es6,es7,jsx。

    module.exports = {
      module:{
        rules:[
          {
            test:/\.js|jsx$/,
            exclude:/node_modules/, //不处理node_modules这个文件夹,这里不需要引号
            use:[{
              loader:'babel-loader',
              options:{presets:['es2015','react']}     
            }],
          }
        ]
      }
    }
    
    Babel配置选项

    babel有自己的配置项,一般都会把babel的配置项放在一个名为“.babelrc”的配置文件中.

    {
      "presets":["react","es2015"]
    }
    

    css

    webpack提供两个工具处理样式表,css-loaderstyle-loader,[css-loader][]可以让我们使用@importurl(...)的方法实现require()的功能,比如在react中,我们直接通过import 'xxx.css'来引入css,style-loader可以将所有的计算后的样式加入页面的内联样式中。

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

    注意:style!css中,加感叹号的作用在于使同一文件能够使用不同类型的loader

    多个loader可以用在同一个文件上并且被链式调用,链式调用时从右到左执行且loader之间用“!”来分割。

    • webpack在入口文件内搜索依赖项,发现有css依赖。
    • css文件交给css-loader去处理
    • css处理完之后,webpack将处理结果交给style-loader去处理

    CSS module

    可以让css产生作用域的效果即scope

    module.exports = {
      module:{
        rules:[
          {
            test:/\.css$/,
            use:['style-loader','css-loader?module'] //在css加载器后面加了一个module
          }
        ]
      }
    }
    

    现在创建一个root.css文件

    .root{background-color:red}
    

    在jsx中引入

    import React from 'react';
    import './root.css';
    export default class liberty extends React.Component{
      render(){
        return (
            <div className = 'root'> // 添加类名
            </div>
        )
      }
    }
    

    这个时候,其他组件如果也要使用root这个类名,不会造成污染。

    自动添加css兼容性前缀

    需要[postcss-loader][]和[autoprefixer][]插件

    module.exports = {
      module:{
        rules:[
          {
            test:/\.css$/,
            use:['style-loader','css-loader?module!postcss']
          }
        ]
      },
      postcss:[
        require('autoprefixer') //调用autoprefixer插件
      ]
    }
    

    常用命令

    $ webpack --config webpack.min.js //另一份配置文件,作为生产和开发环境的区分
    
    $ webpack --display-error-details //显示异常信息
    
    $ webpack --watch   //监听变动并自动打包
     
    $ webpack -p    //压缩混淆脚本,这个非常非常重要!
     
    $ webpack -d    //生成map映射文件,告知哪些模块被最终打包到哪里了
    

    常用插件

    ExtractTextPlugin:可以从bundle中提取出特定的内容到一个文件中,可以抽离公共样式

    let ExtractTextPlugin = require("extract-text-webpack-plugin");
    let extractCSS = new ExtractTextPlugin('stylesheets/[name].css');
    module.exports = {
      module:{
        rules:[
          {
            test:/\.css/,
            use:extractCSS.extract(['css','sass'])
          }
        ]
      }
      plugins:[
        extractCSS
      ]
    }
    

    CommonsChunkPlugin:可以将多个入口中的公共内容提取出来。

    CommonsChunk:可以用来解决多个js引用了同一个文件导致该文件多次请求的情况,它会把这个文件打包进一个公共的文件内,被浏览器缓存。

    module.exports = {
      plugins:[
        new webpack.optimize.CommonsChunkPlugin({
          name:"commons",
          filename:"commons.js",
          minChunks:2 //加载次数
        })
      ]
    }
    

    现在的如果有任意模块被加载了两次或更多,它就会被打包进一个叫commons.js的文件里。

    相关文章

      网友评论

        本文标题:webpack

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