webpack

webpack4.0 基础知识

2019-07-04  本文已影响0人  成熟稳重的李先生

1. webpack基础配置

webpack4.0必须安装webpack和wabpck-cli

webpack可以0配置,它默认支持js模块化,因此可以使用commonjs语法

1.基础配置项

配置文件的默认名为webpack.config.js或者webpackfile.js,(自定义名称的话可再命令中添加config参数)

output:{
    filename: 'bundle.js',   // 打包后的文件名
    path: path.resolve(__dirname, 'dist')   // 路径必须是绝对路径,(先引入path模块)
  }

2.webpack打包出的文件解析

3.Html插件

devServer: {
    port: 3000,
    progress: true,  //  打包进度条
    contentBase: './dist',  //根地址对应路径
    compress: true  // 是否启用gzip压缩
  },
plugins: [  //放着所有的webpack插件
   new HtmlWebpackPlugin({
      template: './src/index.html',
      filename: 'index.html',
      minify: {
        removeAttributeQuotes: true,
        collapseWhitespace: true
      },
      hash: true
    })
]

4.模块处理(或者.vue,.js等等文件)

主要用于处理非js模块(es6 to es5),需要在module中配置相应处理规则和加载器,以下,先以样式处理为例子

module: {
    rules: [
      {
        test: /\.scss$/,  // sass-loader node-sass, less less-loader, stylus stylus-loader
        use: [
          {
            loader: 'style-loader',
            options: {
              insertAt: 'top'
            }
          },
          'css-loader',
          'sass-loader'
        ]
      }
    ]
  },

style-loader会把样式以<style>标签的形式插入到head标签中,如果要将样式单独抽离成css文件,就需要用到插件‘mini-css-extract-plugin’了

let MiniCssExtractPlugin = require('mini-css-extract-plugin');   //引入插件(得先安装);
module: {
    rules: [
      {
        test: /\.(sc|c)ss$/,  // sass-loader node-sass, less less-loader, stylus stylus-loader
        use: [
          MiniCssExtractPlugin.loader,  //此处就不用了‘style-loader’了
          'css-loader',
          'sass-loader'
        ]
      }
    ]
  },
plugins: [
    new MiniCssExtractPlugin({
      filename: 'main.css'
    })
  ]

如果用到css3的新功能,那么就需要加前缀,首先装包 postcss-loader, autoprefixer,然后需要配置postcss的config文件(postcss.config.js)

// postcss.config.js文件
 module.exports = {
  plugins: [require('autoprefixer')]
}
//webpack.config.js文件
module: {
    rules: [
      {
        test: /\.(sc|c)ss$/,  // sass-loader node-sass, less less-loader, stylus stylus-loader
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',  //先预处理css,得出结果后才用css-loader
          'sass-loader'
        ]
      }
    ]
  },

如果要压缩css,首先,配置文件中,mode需设置为“production”,然后在webpack配置文件中添加字段“optimization”,用插件optimize-css-assets-plugin压缩CSS

optimization: {
    minimizer: [
      new OptimizeCss(),
      new TerserJs({
        cache: true,
        sourceMap: true
      })
    ]
  }

处理js模块(es6 -> es5),首先安装模块加载器‘babel-loader’,然后安装babel核心模块“@babel/core”,最后安装转换规则(es6,es7,提案阶段...)模块,这里我们使用“@babel/preset-env”

module: {
    rules: [
      {
        test: /\.(sc|c)ss$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader",
          "sass-loader"
        ]
      },
      {
        test: /\.js$/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
            plugins: ["@babel/plugin-proposal-class-properties"]   //这个插件是为了转换es7的class语法
          }
        }
      }
    ]
 },

babel默认不转化新的API,需要“@babel/plugin-transform-runtime”来转化(但是比如“foobar”.includes(“foo”),Object.assign等就需要安装@babel/polyfill),这个包是开发依赖,上线也需要支持新的语法,因此还需要“@babel/runtime”,将其添加至plugins。同时,转化js应该避开node_modules
文件夹

{
        test: /\.js$/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
            plugins: [
              ["@babel/plugin-proposal-class-properties"],
              ["@babel/plugin-transform-runtime"]
            ]
          }
        },
        include: path.resolve('dist'),
        exclude: /node_modules/
      }

4.配置eslint

eslint是js的语法校验规则,可以去官网demo处下载eslint.json文件,根据自己的需求添加校验规则。

loader的执行顺序是右向左,下向上,因此匹配到js是,先校验,然后才进行转化语法,压缩等操作,use中有字段“enforce”来指定loader执行顺序,如下

//为了灵活配置(比如后期可能不需要eslint了),因此将eslint规则单独放开
  {
        test: /\.js$/,
        enforce: 'pre'   //pre,post(此处有坑,eslint-loader文档中写的是和“loader”字段同级,经实测,可放在这里,也可放在loader的options中)
        use: [
          {
            loader: 'eslint-loader' 
          }
        ]
      },
      {
        test: /\.js$/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
            plugins: [
              ["@babel/plugin-proposal-class-properties"],
              ["@babel/plugin-transform-runtime"]
            ]
          }
        },
        include: path.resolve("src"),
        exclude: /node_modules/
      }

5.第三方模块的使用

我们以jquery为例

//index.js
import $ from "jquery"
console.log($)
//在做传统项目时,如果引入了jquery,那么在全局都可以使用(绑定在了window上)
//那么我们打印一下“window.$”
console.log(window.$)
005236.png
window.$是undefined
此时,我们可以使用“expose-loader”,暴露全局的loader,这是内联loader。(loader类型,pre-前置,post-后置,normal-普通loader,内联loader)
import $ from "expose-loader?$!jquery";
console.log($);

console.log(window.$);
005854.png

当然,也可以写成普通loader的方式

 module: {
    rules: [
      {
        test: require.resolve("jquery"),
        use: "expose-loader?$"
      }
]

还可以不在每个页面引入,直接把jquery集成到webpack配置中

首先引入webpack,然后调用webpack自带的providePlugin

new webpack.ProvidePlugin({
    $: "jquery"
  })

可是打包之后,发现bundle.js文件过大,将jquery也打包进去了,这时可以将JS引用方式改为CDN引入。
然后在webpack配置文件中添加externals字段

externals: {
    jquery: "jQuery"
  },

webpack在打包时,会分析每个包的依赖,像jquery这种不依赖任何包的包,解析是没有必要的,它会拖慢打包速度,这是,可以在module中添加字段“noParse”

module: {
 npParse: /jquery/  //不去解析jquery的依赖库
}

6.webpack打包图片

常规项目中我们要使用image,一般有三种方式:

//1.js导入
var Img = new Image(); 
Img.src = './image.png'; 
document.body.appendChild(Img);
//2.css中元素背景
body{
  background: url('./image.png') 100%/center;
}
//3.html中
<img src="./image.png">

在webpack中,如果以JS方式引用图片,得先在webpack配置文件中加上“file-loader”)

//webpack.config.js
...
modlue: {
  rules: [
    {
        test: /\.(jpg|png|gif)$/,
        use: 'url-loader'
      }
  ]
}
...
//1.js导入
let imgFile = require('./image.png')//以模块的方式导入
var Img = new Image(); 
Img.src = './image.png';  //在webpack项目中,打包后以这种相对路径的方式引用图片资源是不行的,必须先以模块的方式导入(以上require)
document.body.appendChild(Img);
//2.css中引入
//因为引入了css-loade,在css文件中,“background:url('./logo.png')”会被自动转化为“background:url(require('./logo.png'))”,因此,不用做特殊处理
//3.在html中引入,同理,打包后的文件不能从“./”目录找到相应的资源,这时可以使用插件“html-withimg-loader”
//webpack.config.js
module: {
  rules: [
    {
      test: /\.html$/,
      use: 'html-withimg-loader'
    }
  ]
}

如果图片较小时,为了减少http请求,可以将图片转为base64,要用到加载器“url-loader”

rules: [
  {
    test: /\.(jpg|png|gif)$/,
    // 可以给一个限制,图片大小小于某个值时,转为base64,否则会自动使用“flie-loader”将文件拷贝至生产目录。(如果想让img文件都存放在特定的文件夹中,可以指定“name”参数)
    use: {
       loader:  'url-loader',
        options: {
          limit: 200*1024,
          name: image/[name].[hash:5].[ext]
        }
    }
  }
]
// 同理,生成的css类文件也可以放在指定文件夹中,只需在文件名前加路径
plugins: [  //放着所有的webpack插件
    ....
    new MiniCssExtractPlugin({
      filename: 'css/main.css'
    })
  ]

在浏览器中运行


browser1.png

6.文件分块打包

以上,在正式环境中,如果img,js,css等资源都要放到cdn服务器上,那么像“image/logo1.png”就得变成“https://xxx.xxxx.xx/image/logo1.png”这种形式。此时,可以在webpack配置文件的output中添加publicPath字段来指定域名

output: {
    filename: 'bundle.[hash:5].js', //打包后的文件名
    path: path.resolve(__dirname, 'dist'),
    publicPath: 'http://www.baidu.com'
  },
browser2.png

如果只有某种文件上cdn,比如图片,可以将publicPath写到对应处理规则中,但output中的对应字段得删掉

{
        test: /\.(jpg|png|gif)$/, // 可以给一个限制,图片大小小于某个值时,转为base64,否则还是使用file-loader
        use: {
           loader:  'url-loader',
            options: {
              limit: 1,
              name: 'img/[name].[ext]',
              publicPath: 'http://xxx.xxxx.xx'
            }
        }
      }
上一篇 下一篇

猜你喜欢

热点阅读