webpack4.x 总结

webpack作用

  • 打包(把多个文件打包成一个js文件,减少服务器的压力、减少请求)
  • 转化 (比如 less、sass、ts,需要loader转化器)
  • 优化(SPA页面,前端项目复杂度增加,webpack优化)

webpack构成

  • 入口 entry
  • 出口 output
  • loaders 转化器
  • plugins 插件
  • devServer 开发服务器
  • mode

安装webpack

npm install webpack webpack-cli -g
验证:webpack -v

扩展:npm
安装:
npm install jquery --save-dev
可以写成:
npm i jquery -D

npm install jquery --save
可以写成:
npm i jquery -S

卸载

npm unistall jquery --save-dev
可以写成:
npm un jquery -D

webpack配置

  • 1:默认 webpack.config.js
套路:就是由这几部分组成
module.exports = {
  entry: { },         // 入口配置
  output: { },       // 出口配置
  module: { },     // 模块规则,module.rules,用来配置各种loader
  plugins: [ ],      // 插件 数组
  devServer: { }  // 服务器
};


实例:最简单测试
const path = require('path'); // 这是node内置的模块
console.log(path.resolve(__dirname, 'dist'));  // path.resolve表示合并,__dirname也是node内置的,表示该项目的根目录,这里就表示: C:\E\教程\webpack\demo1,所以合并的结果就是:C:\E\教程\webpack\demo1\dist
module.exports = {
  entry: {
    a: './src/index.js'
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  }
};

注意:除了使用默认的webpack.config.js配置文件外,还可以自己指定相应的配置文件:
方法1:webpack --config webpack.config.dev.js
方法2:利用node,在package.json中的scripts配置
如:

  "scripts": {
    "build": "webpack --config webpack.config.dev.js"
  },

在cmd直接运行:node run build

webpack4.x 总结_第1张图片
最简单测试

多入口(多文件),插件 html-webpack-plugin

  • 基础
webpack配置:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: { // 多入口 key-value
    index: './src/index.js',
    index2: './src/index2.js',
  },
  output: { // 多出口,出口的名字,通过内部定义好的变量 [name] 拿到出口文件的 key
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].bundle.js'
  },
  mode: 'production',
  plugins: [
    new HtmlWebpackPlugin({
      title: 'i love u',
      hash: true,
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeAttributeQuotes: true
      }
    })
  ]
};


说明:html-webpack-plugin
1:html-webpack-plugin依赖 webpack、webpack-cli模块
2:安装:npm i --save-dev html-webpack-plugin
3:引入:const HtmlWebpackPlugin = require('html-webpack-plugin');
4:使用:plugins: [
  new HtmlWebpackPlugin({})
]
5:注意在配置title的时候,需要在模板中的title修改:
<%= htmlWebpackPlugin.options.title %>

  • 进阶 利用html-webpack-plugin 生成多个页面,或者多个页面分别引入自己的js;这个配置使用了另一个插件clean-webpack-plugin

注意:如果使用 optimization.splitChunks 这里要注意html-webpack-plugin的chunks属性可能会影响。

配置:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const cleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
  entry: {
    index: './src/index.js',
    index2: './src/index2.js',
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].bundle.js'
  },
  mode: 'development',
  plugins: [
    new cleanWebpackPlugin(['dist']), // 打包之前,先清除掉之前打的包
    new HtmlWebpackPlugin({ // 多个HtmlWebpackPlugin,打包生成多个页面,要指定filename
      title: 'i love u',
      hash: true,
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeAttributeQuotes: true
      },
      filename: 'index3.html', // 打完包的名字,自己决定
      chunks: ['index'] // 跟入口文件的key对应,引入自己的js
    }),
    new HtmlWebpackPlugin({
      title: 'u love i',
      hash: true,
      template: './src/index2.html',
      minify: {
        collapseWhitespace: true,
        removeAttributeQuotes: true
      },
      filename: 'index2.html',
      chunks: ['index2']
    }),
  ]
};

说明:
1:需要打包几个文件,就配置几个new HtmlWebpackPlugin;
2:对应配置的new HtmlWebpackPlugin 可以分别配置不同的模板,通过配置 filename 来区分最后打包出来的文件名,filename值可以自己随便定义;
3:可以通过配置 chunks ,来指定这个 HtmlWebpackPlugin 的模板需要引入哪些自己的模块,这个值,是跟entry入口文件中的key对应。
4:对于clean-webpack-plugin插件,直接new cleanWebpackPlugin(['dist'])配置打包前需要清除的文件夹即可,是数组。

开发环境需要的服务:webpack-dev-server

1:安装
npm i webpack-dev-server -D

2:配置(不用require)
  devServer: {
    contentBase: './dist',
    host: 'localhost',
    port: '8888',
    open: true, // 自动开发游览器
    hot: true // 热更新,这里需要配置webpack内置的HotModuleReplacementPlugin插件,不然会报错
  }

3:使用webpack-dev-server 打包,并不会生成文件,只会在内存里,所以看不到打包出来的文件。

4:利用package.json进行打包:
  "scripts": {
    "build": "webpack --config webpack.config.pro.js",
    "dev": "webpack-dev-server --config webpack.config.dev.js"
  },


5:完整配置文件:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const cleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
module.exports = {
  entry: {
    index: './src/index.js',
    index2: './src/index2.js',
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].bundle.js'
  },
  mode: 'production',
  plugins: [
    new webpack.HotModuleReplacementPlugin, // 热更新需要引入这个插件
    new cleanWebpackPlugin(['dist']), // 打包之前,先清除掉之前打的包
    new HtmlWebpackPlugin({ // 多个HtmlWebpackPlugin,打包生成多个页面,要指定filename
      title: 'i love u',
      hash: true,
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeAttributeQuotes: true
      },
      filename: 'index.html', // 打完包的名字,自己决定
      chunks: ['index', 'index2'] // 跟入口文件的key对应,引入自己的js
    }),
  ],
  devServer: {
    contentBase: './dist',
    host: 'localhost',
    port: '8888',
    open: true, // 自动开发游览器
    hot: true // 热更新,这里需要配置webpack内置的HotModuleReplacementPlugin插件,不然会报错
  }
};

loaders

预先说明

  • a:module中rules中的三种写法
例:
  module: {
    rules: [
      {
        test: /\.css$/,
        // 注意:对于css,必须先使用css-loader,再使用style-loader
        // use: ['style-loader', 'css-loader']         // 第一种写法
        // loader: ['style-loader', 'css-loader']      // 第二种写法
        use: [                                         // 第三种写法
          { loader: 'style-loader' },
          { loader: 'css-loader' }
        ]
      }
    ]
  },
  • b:打包完上线肯定要压缩
1:方式一:利用mode  
利用webpack4x 的特性,mode
生产:压缩
      mode  --production
开发:不压缩
      mode  --development


2:方式二:使用插件 uglifyjs-webpack-plugin
      1:安装:npm i -D uglifyjs-webpack-plugin
      2:const Uglify = require('uglifyjs-webpack-plugin');
      3:new Uglify()

1:css
使用的loader:style-loader、css-loader

1:安装 npm i style-loader css-loader -D
2:配置loader:
  module: {
    rules: [
      {
        test: /\.css$/,
        // 注意:对于css,必须先使用css-loader,再使用style-loader
        // use: ['style-loader', 'css-loader']         // 第一种写法
        // loader: ['style-loader', 'css-loader']      // 第二种写法
        use: [                                         // 第三种写法
          { loader: 'style-loader' },
          { loader: 'css-loader' }
        ]
      }
    ]
  },

说明:
1:loader的加载顺序是从右往左的,所以,需要先加载css-loader,再加载style-loader:
2:这里指支持css,后面要扩展 sass、less和使用postcss

分离css:使用的插件 extract-text-webpack-plugin

1:安装:这个插件对于webpack4x的安装需要使用下个版本
npm i extract-text-webpack-plugin@next -D
2:引入:
const ExtractTextPlugin = require('extract-text-webpack-plugin');
3:使用:
new ExtractTextPlugin('css/style.css')  // 分离打包后的css存放的路径
4:对css load规则进行修改配置:
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: 'css-loader',
          publicPath: '../'  

        })
      },

//对 publicPath: '../' 说明: 因为我们图片使用outputPath存放的路径为images目录,
// 而css打包后 new ExtractTextPlugin('css/style.css')  存放的目录为css/style.css,
// 所以,对于图片,style.css寻找文件时,需要往上一层找


webpack4.x 总结_第2张图片
打包后的文件目录

2:图片
使用的loader:url-loader、file-loader

1:安装:npm i url-loader file-loader -D
2:配置:
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 70000, // 限制70kb的时候,使用base64压缩,如果大于的话,则使用路径
              outputPath: 'images' // 大于70kb,图片打包存放的在images目录下
            }
          }
        ]
      }

处理 less、sass和使用postcss处理前缀

  • less:使用less-loader
1:安装:
npm install --save-dev less-loader less
2:配置:
   {
        test: /\.less$/,
        use: [
          { loader: 'style-loader' },
          { loader: 'css-loader' },
          { loader: 'less-loader' },
        ]
      },

有分离:
   { // 分离less
        test: /\.less$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'less-loader', 'postcss-loader'],
          publicPath: '../'
        })
      },

  • sass:使用sass-loader
1:安装:
npm install sass-loader node-sass webpack --save-dev
2:配置:
 {
        test: /\.(sass|scss)$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },

分离:
 { // 分离
        test: /\.(sass|scss)$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'sass-loader'],
          publicPath: '../'
        })
      },

  • postcss:配置前缀
1:安装:
cnpm i -D postcss-loader 
cnpm i -D autoprefixer // 前缀

在根目录下,新增postcss 的配置文件:postcss.config.js

postcss.config.js配置为:
module.exports = {
  plugins: [
    require('autoprefixer')
  ]
}


以css为例配置postcss:(项目中,也需要为相应的less或者sass配置)
 {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'postcss-loader'],
          publicPath: '../'
        })
      },

优化:使用插件 purifycss-webpack 消除冗余css代码

1:安装:
npm i -D purifycss-webpack purify-css
npm i -D glob // 配置全局路径需要

2:引入:
const glob = require('glob');
const PurifyCSSPlugin = require('purifycss-webpack');

3:配置:
    new PurifyCSSPlugin({
      // Give paths to parse for rules. These should be absolute!
      paths: glob.sync(path.join(__dirname, 'src/*.html')),
    })

sourceMap 关联源码

// 生产调试需要开启源码,实际生产一定要关闭
devtool: 'source-map'

babel

说明:
a:babel是用来编译js
b:可以方便的使用ES各个版本(es6、es7等)
c:jsx语法转化

1:安装:
cnpm i babel-core babel-loader babel-preset-env -D
cnpm i babel-preset-react -D // react 需要的preset
2:在根目录配置.babelrc
{
  "presets": [
    "env",
    "react"
  ]
}

3:配置:
      {
        test: /\.(js|jsx)$/,
        use: [
          {
            loader: 'babel-loader',
          }
        ],
        exclude: /node_modules/
      }


注意,preset也可以直接在use中配置,但是,**不建议**,使用.babelrc可以方便扩展
      {
        test: /\.(js|jsx)$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
                preset: 'evn'
            }
          }
        ],
        exclude: /node_modules/
      }


react

1:安装:
cnpm i react react-dom -S
需要在.babelrc配置react 的preset ,所以需要安装
cnpm i babel-preset-react -D 
2:在根目录配置.babelrc
{
  "presets": [
    "env",
    "react"
  ]
}

webpack用到模块化

例:aa.js
const model = function () {
  return "123"
}

module.exports = model;

说明:通过 module.exports中导出

webpack 中使用 require导入
const aa = require("./aa.js");

webpack4x使用json

例:
test.json:
{
  "port": "8888"
}

webpack使用:
const testConfig = require("./test.json");

说明:webpack3x是需要安装json-loader,4x不需要。

使用第三方库,利用插件 ProvidePlugin

例:
1:const webpack = require('webpack');

2:
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery'
    }),

说明:
1:虽然可以通过 import $ from jQuery;但是,不建议,因为只要一通过import,不管页面有无有到,都会被打包。
2:使用ProvidePlugin插件,只要使用到此库,才会被打包。


optimization.splitChunks

注意:webpack4x已经废弃 CommonsChunkPlugin

  optimization: {
    splitChunks: {
      cacheGroups: {
        vendors: {
          chunks: 'initial',
          name: 'jquery',
          enforce: true
        }
      }
    }
  }

注意:
1:使用optimization时,注意不要给HtmlWebpackPlugin插件,配置chunks,否则,会影响。
2:optimization的上下文是在根路径,与entry、output等同级。

练习最后的webpack配置代码,参考即可

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const cleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const webpack = require('webpack');
const glob = require('glob');
const PurifyCSSPlugin = require('purifycss-webpack');

const ip = require("./ip.config.js");
const jsonConfig = require("./test.json");

console.log(ip);
console.log(ip());
console.log(jsonConfig);
console.log(jsonConfig.port);

module.exports = {
  entry: {
    index: './src/index.js',
    jquery: 'jquery'
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].bundle.js'
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'postcss-loader'],
          publicPath: '../'
        })
      },
      { // 分离less
        test: /\.less$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'less-loader', 'postcss-loader'],
          publicPath: '../'
        })
      },
      // {
      //   test: /\.less$/,
      //   use: [
      //     { loader: 'style-loader' },
      //     { loader: 'css-loader' },
      //     { loader: 'less-loader' },
      //   ]
      // },
      // {
      //   test: /\.(sass|scss)$/,
      //   use: ['style-loader', 'css-loader', 'sass-loader']
      // },
      { // 分离
        test: /\.(sass|scss)$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'sass-loader'],
          publicPath: '../'
        })
      },
      {
        test: /\.(js|jsx)$/,
        use: [
          {
            loader: 'babel-loader',
          }
        ],
        exclude: /node_modules/
      },
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 70000,
              outputPath: 'images'
            }
          }
        ]
      }
    ]
  },
  devtool: 'source-map',
  plugins: [
    new webpack.HotModuleReplacementPlugin,
    new cleanWebpackPlugin(['dist']), // 打包之前,先清除掉之前打的包
    new HtmlWebpackPlugin({ // 多个HtmlWebpackPlugin,打包生成多个页面,要指定filename
      title: 'i love u',
      hash: true,
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeAttributeQuotes: true
      },
      filename: 'index.html', // 打完包的名字,自己决定
      // chunks: ['index'] // 跟入口文件的key对应,引入自己的js
    }),
    new ExtractTextPlugin('css/style.css'),
    new PurifyCSSPlugin({
      // Give paths to parse for rules. These should be absolute!
      paths: glob.sync(path.join(__dirname, 'src/*.html')),
    }),
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery'
    }),
  ],
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendors: {
          chunks: 'initial',
          name: 'jquery',
          enforce: true
        }
      }
    }
  },
  devServer: {
    contentBase: './dist',
    host: 'localhost',
    port: '8888',
    open: true, // 自动开发游览器
    hot: true // 热更新,这里需要配置webpack内置的HotModuleReplacementPlugin插件,不然会报错
  }
};

webpack-dev-server 配置跨域

headers: {'Access-Control-Allow-Origin': '*'}

你可能感兴趣的:(webpack4.x 总结)