webpack

什么是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 (
        
// 添加类名
) } }

这个时候,其他组件如果也要使用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)