• webpack4


    webpack4

    众所周知,webpack进入第4个大版本已经有2个月的时间了,而且webpack团队升级更新的速度也是非常的惊人

    在写下如下内容的时候webpack已经出到了4.6的版本了,剑指5.0应该是指日可待了,当然这些都是个人的臆想,并不代表任何意见

    既然我们已经迎接了webpack4的到来了,那么就一起来使用一下,即使你没用过之前的版本,没关系,我们重新出发,将工作中常用到的配置写给大家来看

    非友情提示:由于webpack使用起来并不能仅看代码就方便理解,所以有图有真相的才是正解,于是乎本文配图很多,真的是很多

    首先,既来之,则安之

    安装webpack

    • 需要先在项目中npm init初始化一下,生成package.json
    • 建议node版本安装到8.2以上
    1.  
      // webpack4中除了正常安装webpack之外,需要再单独安一个webpack-cli
    2.  
       
    3.  
      npm i webpack webpack-cli -D

    ★ npm i -D 是 npm install --save-dev 的简写,是指安装模块并保存到 package.json 的 devDependencies中,主要在开发环境中的依赖包

    0配置了什么

    webpack4可以支持0配置打包,这里所说的0配置又是什么呢?当然在开发者眼中0配置的东西,那根本是无法用的,因为不够智能,那么我们就来看看做到了哪些0配置

    在使用webpack进行打包的时候,默认情况下会将src下的入口文件(index.js)进行打包

    1.  
      // node v8.2版本以后都会有一个npx
    2.  
      // npx会执行bin里的文件
    3.  
       
    4.  
      npx webpack // 不设置mode的情况下 打包出来的文件自动压缩
    5.  
       
    6.  
      npx webpack --mode development // 设置mode为开发模式,打包后的文件不被压缩

    当执行npx webpack命令的时候,webpack会自动查找项目中src目录下的index.js文件,然后进行打包,生成一个dist目录并存在一个打包好的main.js文件

    这些算是0配置的操作了,名字都是定义好的,不能变,想想也很鸡肋

    webpack的使用还是在我们的配置方面,下面就进入我们的常规操作环节

    webpack是基于Node的

    在项目下创建一个webpack.config.js(默认,可修改)文件来配置webpack

    1.  
      module.exports = {
    2.  
      entry: '', // 入口文件
    3.  
      output: {}, // 出口文件
    4.  
      module: {}, // 处理对应模块
    5.  
      plugins: [], // 对应的插件
    6.  
      devServer: {}, // 开发服务器配置
    7.  
      mode: 'development' // 模式配置
    8.  
      }

    以上就是webpack的正常配置模块

    ★ 启动devServer需要安装一下webpack-dev-server

    npm i webpack-dev-server -D
    
    按照项目的结构,我们就从0开始去写一下配置吧
    1.  
      // webpack.config.js
    2.  
       
    3.  
      const path = require('path');
    4.  
       
    5.  
      module.exports = {
    6.  
      entry: './src/index.js', // 入口文件
    7.  
      output: {
    8.  
      filename: 'bundle.js', // 打包后的文件名称
    9.  
      path: path.resolve('dist') // 打包后的目录,必须是绝对路径
    10.  
      }
    11.  
      }

    上面就可以说是实现了最简单的webpack配置了,那接下来就打包一下看看

    配置执行文件

    工作当中我们打包编译的时候一般都执行npm run dev这样的命令,既然是通过npm执行的命令,我们就应该找到package.json里的执行脚本去配置一下命令,这里如下图所示

    npm run build就是我们打包后的文件,这是生产环境下,上线需要的文件

    npm run dev是我们开发环境下打包的文件,当然由于devServer帮我们把文件放到内存中了,所以并不会输出打包后的dist文件夹

    通过npm run build之后会生成一个dist目录文件夹,就和上面打包后的样子一样了

    多入口文件

    多个入口可以有两种实现方式进行打包

    • 一种是没有关系的但是要打包到一起去的,可以写一个数组,实现多个文件打包
    • 另一种就是每一个文件都单独打包成一个文件的
    • 下面就来看看这两种方式的写法
    1.  
      let path = require('path');
    2.  
       
    3.  
      module.exports = {
    4.  
      // 1.写成数组的方式就可以打出多入口文件,不过这里打包后的文件都合成了一个
    5.  
      // entry: ['./src/index.js', './src/login.js'],
    6.  
      // 2.真正实现多入口和多出口需要写成对象的方式
    7.  
      entry: {
    8.  
      index: './src/index.js',
    9.  
      login: './src/login.js'
    10.  
      },
    11.  
      output: {
    12.  
      // 1. filename: 'bundle.js',
    13.  
      // 2. [name]就可以将出口文件名和入口文件名一一对应
    14.  
      filename: '[name].js', // 打包后会生成index.js和login.js文件
    15.  
      path: path.resolve('dist')
    16.  
      }
    17.  
      }

    这时候执行npm run build后,会生成打包好的两个js文件,如图所示

    配置Html模板

    文件都打包好了,但是我们在使用的时候不能在dist目录下去创建一个html文件,然后去引用打包后的js吧,这不合理,实际开发中也不会这样

    我们需要实现html打包功能,可以通过一个模板实现打包出引用好路径的html来

    这就需要用到一个常用的插件了,html-webpack-plugin,用之前我们来安一下它

    npm i html-webpack-plugin -D
    

    因为是个插件,所以需要在config.js里引用一下的

    1.  
      let path = require('path');
    2.  
      // 插件都是一个类,所以我们命名的时候尽量用大写开头
    3.  
      let HtmlWebpackPlugin = require('html-webpack-plugin');
    4.  
       
    5.  
      module.exports = {
    6.  
      entry: './src/index.js',
    7.  
      output: {
    8.  
      // 添加hash可以防止文件缓存,每次都会生成4位的hash串
    9.  
      filename: 'bundle.[hash:4].js',
    10.  
      path: path.resolve('dist')
    11.  
      },
    12.  
      plugins: [
    13.  
      // 通过new一下这个类来使用插件
    14.  
      new HtmlWebpackPlugin({
    15.  
      // 用哪个html作为模板
    16.  
      // 在src目录下创建一个index.html页面当做模板来用
    17.  
      template: './src/index.html',
    18.  
      hash: true, // 会在打包好的bundle.js后面加上hash串
    19.  
      })
    20.  
      ]
    21.  
      }

    通过上面的配置后,我们再npm run build打包看一下现在是个什么样子了

    多页面开发,怎么配置多页面

    如果开发的时候不只一个页面,我们需要配置多页面,那么需要怎么来搞呢?不用担心,html-webpack-plugin插件自有办法,我们来观望一下

    1.  
      let path = require('path');
    2.  
      let HtmlWebpackPlugin = require('html-webpack-plugin');
    3.  
       
    4.  
      module.exports = {
    5.  
      // 多页面开发,怎么配置多页面
    6.  
      entry: {
    7.  
      index: './src/index.js',
    8.  
      login: './src/login.js'
    9.  
      },
    10.  
      // 出口文件
    11.  
      output: {
    12.  
      filename: '[name].js',
    13.  
      path: path.resolve('dist')
    14.  
      },
    15.  
      plugins: [
    16.  
      new HtmlWebpackPlugin({
    17.  
      template: './src/index.html',
    18.  
      filename: 'index.html',
    19.  
      chunks: ['index'] // 对应关系,index.js对应的是index.html
    20.  
      }),
    21.  
      new HtmlWebpackPlugin({
    22.  
      template: './src/login.html',
    23.  
      filename: 'login.html',
    24.  
      chunks: ['login'] // 对应关系,login.js对应的是login.html
    25.  
      })
    26.  
      ]
    27.  
      }

    继续npm run build看打包后的样子

    上面基本介绍完了html和js的打包配置了,现在我们还缺一个好兄弟css,webpack对css的解析需要用到loader,所以我们先提前安装好,待会好方便使用

    引用CSS文件

    可以在src/index.js里引入css文件,到时候直接打包到生产目录下

    需要下载一些解析css样式的loader

    1.  
      npm i style-loader css-loader -D
    2.  
      // 引入less文件的话,也需要安装对应的loader
    3.  
      npm i less less-loader -D

    下面我们来看一下如何配置css文件的解析

    1.  
      // index.js
    2.  
      import './css/style.css'; // 引入css
    3.  
      import './less/style.less'; // 引入less
    4.  
       
    5.  
      console.log('这里是打包文件入口-index.js');
    6.  
       
    7.  
      // webpack.config.js
    8.  
      module.exports = {
    9.  
      entry: {
    10.  
      index: './src/index.js'
    11.  
      },
    12.  
      output: {
    13.  
      filename: 'bundle.js',
    14.  
      path: path.resolve('dist')
    15.  
      },
    16.  
      module: {
    17.  
      rules: [
    18.  
      {
    19.  
      test: /\.css$/, // 解析css
    20.  
      use: ['style-loader', 'css-loader'] // 从右向左解析
    21.  
      /*
    22.  
      也可以这样写,这种方式方便写一些配置参数
    23.  
      use: [
    24.  
      {loader: 'style-loader'},
    25.  
      {loader: 'css-loader'}
    26.  
      ]
    27.  
      */
    28.  
      }
    29.  
      ]
    30.  
      }
    31.  
      }
    • 此时打包后的css文件是以行内样式style的标签写进打包后的html页面中,如果样式很多的话,我们更希望直接用link的方式引入进去,这时候需要把css拆分出来
    • extract-text-webpack-plugin插件相信用过的人都知道它是干什么的,它的功效就在于会将打包到js里的css文件进行一个拆分

    拆分CSS

    1.  
      // @next表示可以支持webpack4版本的插件
    2.  
      npm i extract-text-webpack-plugin@next -D
    1.  
      let path = require('path');
    2.  
      let HtmlWebpackPlugin = require('html-webpack-plugin');
    3.  
      // 拆分css样式的插件
    4.  
      let ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
    5.  
       
    6.  
      module.exports = {
    7.  
      entry: './src/index.js',
    8.  
      output: {
    9.  
      filaneme: 'bundle.js',
    10.  
      path: path.resolve('dist')
    11.  
      },
    12.  
      module: {
    13.  
      rules: [
    14.  
      {
    15.  
      test: /\.css$/,
    16.  
      use: ExtractTextWebpackPlugin.extract({
    17.  
      // 将css用link的方式引入就不再需要style-loader了
    18.  
      use: 'css-loader'
    19.  
      })
    20.  
      }
    21.  
      ]
    22.  
      },
    23.  
      plugins: [
    24.  
      new HtmlWebpackPlugin({
    25.  
      template: './src/index.html',
    26.  
      }),
    27.  
      // 拆分后会把css文件放到dist目录下的css/style.css
    28.  
      new ExtractTextWebpackPlugin('css/style.css')
    29.  
      ]
    30.  
      }

    此时拆分完css后,打包的html页面就以link的方式去引入css了,这样很好

    引用图片

    • 处理图片方面,也需要loader
    npm i file-loader url-loader -D
    

    如果是在css文件里引入的如背景图之类的图片,就需要指定一下相对路径

    1.  
      module.exports = {
    2.  
      module: {
    3.  
      rules: [
    4.  
      {
    5.  
      test: /\.css$/,
    6.  
      use: ExtractTextWebpackPlugin.extract({
    7.  
      use: 'css-loader',
    8.  
      publicPath: '../'
    9.  
      })
    10.  
      },
    11.  
      {
    12.  
      test: /\.(jpe?g|png|gif)$/,
    13.  
      use: [
    14.  
      {
    15.  
      loader: 'url-loader',
    16.  
      options: {
    17.  
      limit: 8192, // 小于8k的图片自动转成base64格式,并且不会存在实体图片
    18.  
      outputPath: 'images/' // 图片打包后存放的目录
    19.  
      }
    20.  
      }
    21.  
      ]
    22.  
      }
    23.  
      ]
    24.  
      }
    25.  
      }

    在css中指定了publicPath路径这样就可以根据相对路径引用到图片资源了,如下图所示

    页面img引用图片

    页面中经常会用到img标签,img引用的图片地址也需要一个loader来帮我们处理好

    npm i html-withimg-loader -D
    
    1.  
      module.exports = {
    2.  
      module: {
    3.  
      rules: [
    4.  
      {
    5.  
      test: /\.(htm|html)$/,
    6.  
      use: 'html-withimg-loader'
    7.  
      }
    8.  
      ]
    9.  
      }
    10.  
      }

    这样再打包后的html文件下img就可以正常引用图片路径了

    引用字体图片和svg图片

    字体图标和svg图片都可以通过file-loader来解析

    1.  
      module.exports = {
    2.  
      module: {
    3.  
      rules: [
    4.  
      {
    5.  
      test: /\.(eot|ttf|woff|svg)$/,
    6.  
      use: 'file-loader'
    7.  
      }
    8.  
      ]
    9.  
      }
    10.  
      }

    这样即使样式中引入了这类格式的图标或者图片都没有问题了,img如果也引用svg格式的话,配合上面写好的html-withimg-loader就都没有问题了

    添加CSS3前缀

    通过postcss中的autoprefixer可以实现将CSS3中的一些需要兼容写法的属性添加响应的前缀,这样省去我们不少的时间

    由于也是一个loader加载器,我们也需要先安装一下

    npm i postcss-loader autoprefixer -D
    

    安装后,我们还需要像webpack一样写一个config的配置文件,在项目根目录下创建一个postcss.config.js文件,配置如下:

    1.  
      module.exports = {
    2.  
      plugins: [require('autoprefixer')] // 引用该插件即可了
    3.  
      }

    然后在webpack里配置postcss-loader

    1.  
      module.exports = {
    2.  
      module: {
    3.  
      rules: [
    4.  
      {
    5.  
      test: /\.css$/,
    6.  
      use: ['style-loader', 'css-loader', 'postcss-loader']
    7.  
      }
    8.  
      ]
    9.  
      }
    10.  
      }

    转义ES6

    在实际开发中,我们在大量的使用着ES6及之后的api去写代码,这样会提高我们写代码的速度,不过由于低版本浏览器的存在,不得不需要转换成兼容的代码,于是就有了常用的Babel了

    Babel会将ES6的代码转成ES5的代码

    那么不再多说,既然要使用它,就先来安一下

    npm i babel-core babel-loader babel-preset-env babel-preset-stage-0 -D
    

    当把这些都安好后,我们就开始配置,由于要兼容的代码不仅仅包含ES6还有之后的版本和那些仅仅是草案的内容,所以我们可以通过一个.babelrc文件来配置一下,对这些版本的支持

    1.  
      // .babelrc
    2.  
      {
    3.  
      "presets": ["env", "stage-0"] // 从右向左解析
    4.  
      }

    我们再在webpack里配置一下babel-loader既可以做到代码转成ES5了

    1.  
      module.exports = {
    2.  
      module: {
    3.  
      rules: [
    4.  
      {
    5.  
      test:/\.js$/,
    6.  
      use: 'bable-loader',
    7.  
      include: /src/, // 只转化src目录下的js
    8.  
      exclude: /node_modules/ // 排除掉node_modules,优化打包速度
    9.  
      }
    10.  
      ]
    11.  
      }
    12.  
      }

    在我们每次npm run build的时候都会在dist目录下创建很多打好的包,如果积累过多可能也会混乱

    所以应该在每次打包之前将dist目录下的文件都清空,然后再把打好包的文件放进去

    这里提供一个clean-webpack-plugin插件

    npm i clean-webpack-plugin -D
    
    1.  
      let CleanWebpackPlugin = require('clean-webpack-plugin');
    2.  
       
    3.  
      module.exports = {
    4.  
      plugins: [
    5.  
      // 打包前先清空
    6.  
      new CleanWebpackPlugin('dist')
    7.  
      ]
    8.  
      }

    启动静态服务器

    启动一个静态服务器,默认会自动刷新,就是说你对html,css,js文件做了修改并保存后,浏览器会默认刷新一次展现修改后的效果

    正常情况下我们都是在开发环境中开发项目,所以之前配置的脚本"dev"可以派上用场了,在执行npm run dev命令后,会启动静态服务器,我们访问localhost:3000端口就可以看到开发的页面内容了

    如果devServer里open设为true后,会自动打开浏览器

    1.  
      module.exports = {
    2.  
      devServer: {
    3.  
      contentBase: './dist',
    4.  
      host: 'localhost', // 默认是localhost
    5.  
      port: 3000, // 端口
    6.  
      open: true, // 自动打开浏览器
    7.  
      hot: true // 开启热更新
    8.  
      }
    9.  
      }

    当然在npm run dev命令下,打包的文件存在于内存中,并不会产生在dist目录下

    热更新和自动刷新的区别

    在配置devServer的时候,如果hot为true,就代表开启了热更新

    But这并没那么简单,因为热更新还需要配置一个webpack自带的插件并且还要在主要js文件里检查是否有module.hot

    下面就让我们直接看下代码是如何实现的

    1.  
      // webpack.config.js
    2.  
      let webpack = require('webpack');
    3.  
       
    4.  
      module.exports = {
    5.  
      plugins: [
    6.  
      // 热替换,热替换不是刷新
    7.  
      new webpack.HotModuleReplacementPlugin()
    8.  
      ],
    9.  
      devServer: {
    10.  
      contentBase: './dist',
    11.  
      hot: true,
    12.  
      port: 3000
    13.  
      }
    14.  
      }
    15.  
       
    16.  
      // 此时还没完虽然配置了插件和开启了热更新,但实际上并不会生效
    17.  
       
    18.  
      // index.js
    19.  
      let a = 'hello world';
    20.  
      document.body.innerHTML = a;
    21.  
      console.log('这是webpack打包的入口文件');
    22.  
       
    23.  
      // 还需要在主要的js文件里写入下面这段代码
    24.  
      if (module.hot) {
    25.  
      // 实现热更新
    26.  
      module.hot.accept();
    27.  
      }

    以上index.js中的内容,如果将变量a的值进行修改保存后,会在不刷新页面的情况下直接修改掉,这样就实现了热更新

    那么热更新从现在看来和自动刷新浏览器的区别也不是太大嘛!自动刷新也是可以接受的啊

    其实不然,热更新的好处可能在vue或者react中有更大的发挥,其中某一个组件被修改的时候就会针对这个组件进行热更新了,这里用到vue或react的同学去实际体验一下吧

    resolve解析

    在webpack的配置中,resolve我们常用来配置别名和省略后缀名

    1.  
      module.exports = {
    2.  
      resolve: {
    3.  
      // 别名
    4.  
      alias: {
    5.  
      $: './src/jquery.js'
    6.  
      },
    7.  
      // 省略后缀
    8.  
      extensions: ['.js', '.json', '.css']
    9.  
      },
    10.  
      }

    这个配置在webpack中比较简单,我们也就不再叙述了,下面来看点干货

    提取公共代码

    在webpack4之前,提取公共代码都是通过一个叫CommonsChunkPlugin的插件来办到的。到了4以后,内置了一个一模一样的功能,而且起了一个好听的名字叫“优化”

    下面我们就来看看如何提取公共代码

    1.  
      // 假设a.js和b.js都同时引入了jquery.js和一个写好的utils.js
    2.  
      // a.js和b.js
    3.  
      import $ from 'jquery';
    4.  
      import {sum} from 'utils';

    那么他们两个js中其中公共部分的代码就是jquery和utils里的代码了

    可以针对第三方插件和写好的公共文件

    1.  
      module.exports = {
    2.  
      entry: {
    3.  
      a: './src/a.js',
    4.  
      b: './src/b.js'
    5.  
      },
    6.  
      output: {
    7.  
      filename: '[name].js',
    8.  
      path: path.resolve('dust')
    9.  
      },
    10.  
      // 提取公共代码
    11.  
      + optimization: {
    12.  
      splitChunks: {
    13.  
      cacheGroups: {
    14.  
      vendor: { // 抽离第三方插件
    15.  
      test: /node_modules/, // 指定是node_modules下的第三方包
    16.  
      chunks: 'initial',
    17.  
      name: 'vendor', // 打包后的文件名,任意命名
    18.  
      // 设置优先级,防止和自定义的公共代码提取时被覆盖,不进行打包
    19.  
      priority: 10
    20.  
      },
    21.  
      utils: { // 抽离自己写的公共代码,utils这个名字可以随意起
    22.  
      chunks: 'initial',
    23.  
      name: 'utils', // 任意命名
    24.  
      minSize: 0 // 只要超出0字节就生成一个新包
    25.  
      }
    26.  
      }
    27.  
      }
    28.  
      + },
    29.  
      plugins: [
    30.  
      new HtmlWebpackPlugin({
    31.  
      filename: 'a.html',
    32.  
      template: './src/index.html', // 以index.html为模板
    33.  
      + chunks: ['vendor', 'a']
    34.  
      }),
    35.  
      new HtmlWebpackPlugin({
    36.  
      filename: 'b.html',
    37.  
      template: './src/index.html', // 以index.html为模板
    38.  
      + chunks: ['vendor', 'b']
    39.  
      })
    40.  
      ]
    41.  
      }

    通过以上配置,可以把引入到a.js和b.js中的这部分公共代码提取出来,如下图所示

    指定webpack配置文件

    在package.json的脚步里,我们可以配置调用不同的webpack配置文件进行打包,举个栗子

    这样的好处在于可以针对不同的需求进行一个特定的打包配置

    就到这里吧

    关于webpack4的一些常规操作就说到这里了,其实在工作当中更多时候,也并不需要我们去配置这些内容

  • 相关阅读:
    JUC-狂神笔记整理学习
    多线程-学习笔记
    Redis分布锁
    Redis
    springcloud一个简单的基本流程
    Nacos
    mysql单表查询
    mysql多表查询
    mysql数据库
    mysql详细安装教程以及1067错误代码解决方案
  • 原文地址:https://www.cnblogs.com/fqh123/p/9535203.html
Copyright © 2020-2023  润新知