4. 1.Webpack4-基础

231 阅读3分钟

一、webpack的基础配置

  1. 本地安装webpack
  2. 初始化 yarn init -y
  3. yarn add webpack webpack-cli -D
  4. npx webpack 执行webpack
  5. webpack可以进行0配置
    1. 打包工具->输出的结果(js模块)
    2. 打包(支持js模块化),module.exports+require
  6. 手动配置webpack
    1. 默认配置文件的名字 webpack.config.js
    2. webpack.config.js
// webpack是node写出来的
let path = require('path');
module.exports = {
  mode: 'development', // 模式 默认两种 production development
  entry: './src/index.js', // 入口
  output: {
    filename: 'bundle.js', // 打包后的文件
    path: path.resolve(__dirname, 'build'), // 路径必须是一个绝对路径
  }
}
3. 配置文件可以是webpack.config.js也可以是webpackfile.js

二、webpack打包出的文件解析

  1. 解析配置后的文件
  2. 自定义配置文件
    1. $ npx webpack --config webpack.config.my.js
    2. 脚本配置 package.json
  "scripts": {
    "build": "webpack --config webpack.config.my.js"
  },

三、Html插件

  1. 开发服务器的配置插件 webpack-dev-server
  2. 安装:$ cnpm i webpack-dev-server ;执行:$ webpack-dev-server
  3. package.json
  "scripts": {
    "build": "webpack --config webpack.config.js",
    "dev": "webpack-dev-server"
  },
  1. 开发服务器的配置webpack.config.js
  devServer: { // 开发服务器的配置
    port: 3000,
    progress: true,
    contentBase: './build',
    compress: true
  },
  1. 模板插入脚本 html-webpack-plugin
    1. 安装:$ cnpm i html-webpack-plugin
    2. webpack.config.js
let HtmlWebpackPlugin = require('html-webpack-plugin');

  output: {
    filename: 'bundle.[hash:8].js', // 1. 打包后的文件 2. 每次修改产生新的文件,防止覆盖 
    path: path.resolve(__dirname, 'build'), // 路径必须是一个绝对路径
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      filename: 'index.html',
      minify:{ // 压缩html
        removeAttributeQuotes: true, // 删除html双引号
        collapseWhitespace:true // html变成一行
      },
      hash: true // 设置hash戳
    })
  ]

四、样式处理1

  1. loader
    1. 模块转换
    2. 特点:功能单一
    3. 用法:字符串只用一个loader,多个loader需要[],还可以写成对象方式
    4. loader的顺序,默认是从右向左执行,从下向上
  2. 安装插件 $ cnpm i less less-loader css-loader style-loader
  3. less less-loader css-loader style-loader node-sass sass-loader stylus stylus-loader
  4. css-loader 接续 @import这种语法
  5. style-loader 把css插入到head的标签中
  6. webpack.config.js
  module: { // 模块
    rules: [ // 规则
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader',
            options: {
              insertAt: 'top'
            }
          },
          'css-loader'
        ]
      },
      {
        test: /\.less$/,
        use: [
          {
            loader: 'style-loader',
            options: {
              insertAt: 'top'
            }
          },
          'css-loader',
          'less-loader'
        ]
      }
    ]
  }

五、样式处理2

  1. 抽离css文件
  2. 安装插件 mini-css-extract-plugin
  3. webpack.config.js 添加
let MiniCssExtractPlugin = require('mini-css-extract-plugin');

  plugins: [
    
    new MiniCssExtractPlugin({
      filename: 'main.css'
    })
  ],
  
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader'
        ]
      },
  1. 自动给css填前缀 -webkit-...
  2. 安装插件 postcss-loader autoprefixer
  3. 根目录新建postcss.config.js
module.exports = {
  plugins: [require('autoprefixer')]
}
  1. webpack.config.js 添加
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader'
        ]
      },
  1. 压缩css:插件mini-css-extract-pluin,搜索npmjs.org查找
  2. webpack.config.js 添加
let OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
let UglifyJsPlugin = require('uglifyjs-webpack-plugin');

  optimization: { // 优化项
    minimizer: [
      new UglifyJsPlugin({
        cache: true,
        parallel: true,
        sourceMap: true
      }),
      new OptimizeCSSAssetsPlugin()
    ]
  },

六、转化es6语法

  1. babel转化es6 => es5
  2. 安装插件:babel-loader @babel/core @babel/preset-env
  3. webpack.config.js 添加
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [ // 预设
                '@babel/preset-env'
              ]
            }
          }
        ]
      },
  1. 解析es7语法 class A {a=1};
  2. 安装插件 @babel/plugin-proposal-class-properties
  3. webpack.config.js 添加
            options: {
              presets: [ // 预设
                '@babel/preset-env'
              ],              
              plugins:[
                "@babel/plugin-proposal-class-properties"
              ]
            }
  1. 解析装饰器语法 @log class A{a=1} function log(target){console.log(target)}
  2. 安装插件 @babel/plugin-proposal-decorators
  3. webpack.config.js 添加
            options: {
              presets: [ // 预设
                '@babel/preset-env'
              ],
              plugins:[
                ["@babel/plugin-proposal-decorators", { "legacy": true }],
                ["@babel/plugin-proposal-class-properties", { "loose" : true }]
              ]
            }

七、处理js语法及校验

  1. 公共方法抽离
  2. 安装插件 $ cnpm i @babel/runtime @babel/plugin-transform-runtime -S;
  3. 使用 webpack.config.js 修改
      {
        test: /\.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [ // 预设
              '@babel/preset-env'
            ],
            plugins: [
              ["@babel/plugin-proposal-decorators", { "legacy": true }],
              ["@babel/plugin-proposal-class-properties", { "loose": true }],
              "@babel/plugin-transform-runtime"
            ]
          }
        },
        include: path.resolve(__dirname, 'src'), // 只解析include包括文件
        exclude: /node_modules/ // exclude 排除掉node_modules;
      },
  1. 高级语法(例:'aaa'.includes('a');)解析:
  2. 安装插件 @babel/polyfill
  3. 在使用文件中引入 require('@babel/polyfill');
  4. eslint代码校验:
  5. eslint网站下载.eslintrc.json
  6. 安装插件 $ cnpm i eslint eslint-loader eslint-friendly-formatter -D
  7. webpack.config.js 添加
      {
        test: /\.js$/,
        loader: 'eslint-loader',
        enforce: 'pre',
        include: path.resolve(__dirname, 'src'),
        options: {
          formatter: require('eslint-friendly-formatter')
        },
        exclude: /node_modules/
      },

八、全局变量引入问题

  1. 引入jquery $ cnpm i jquery -S
  2. 使用jquery import $ from 'jquery';var $ = require('jquery');
  3. 使用expose-loader 暴露 全局的jquery 内联的loader
  4. pre 前面执行的loader normal 普通loader 内联loader 后置postloader
  5. 安装插件 expose-loader 使用 import $ from 'expose-loader?$!jquery';, 引入模块配置:webpack.config.js
      {
        test: require.resolve('jquery'),
        use: 'expose-loader?$'
      },
  1. 使用插件对每个模块注入jquery,webpack.config.js
let webpack = require('webpack');

  plugins: [
  
    new webpack.ProvidePlugin({ // 在每个模块中注入jquery
      $: 'jquery'
    })
  ],
  1. 使用cdn,引用但不打包juqery,webpack.config.js
  externals: { jquery: 'jQuery' },
  1. 总结
    1. expose-loader 暴露到window上
    2. providePlugin给每个模块提供一个$
    3. 使用cdn,引入但不打包

九、图片处理

  1. 在js中创建图片来引入
  • 错误引用
let image = new Image();
image.src = '.logo.png'; // 这样就是一个普通的字符串,不会被打包
document.body.appendChild(image);
  • 正确引用图片
import logo from './logo.png'; // 把图片引入,返回的结果是一个新的图片地址
let image = new Image();
image.src = logo; 
document.body.appendChild(image);
  • 安装 file-loader
  • webpack.config.js 添加
      {
        test: /\.(png|jpg|jpeg|gif)$/,
        loader: 'file-loader'
      },
  1. 在css引入 background('url')
  • 直接引入图片地址,使用file-loader
  • require('./index.css');
  1. 在HTML页面中直接插入图片:<img src="" alt="" />
  • 安装插件 html-withimg-loader
      {
        test: /\.html$/,
        loader: 'html-withimg-loader'
      },
  • url-loader 做一个限制 图片大小<是多少k,用base64转化;图片大小>n*K,图片正常产出
      {
        test: /\.(png|jpg|jpeg|gif)$/,
        use:{
          loader: 'url-loader',
          options:{
            limit: 20*1024 // 20*1024 base64;1 正常产出
          }
        }
      },

十、打包文件分类

  1. css放在一个css文件夹下,图片放到images文件夹下
  • webpack.config.js
    new MiniCssExtractPlugin({
      filename: 'css/main.css'
    }),
    
      {
        test: /\.(png|jpg|jpeg|gif)$/,
        use:{
          loader: 'url-loader',
          options:{
            limit: 1,
            outputPath: 'img/',
          }
        }
      },    
  1. publicPath 在引入文件前添加域名前缀
  output: {
    filename: 'bundle.[hash:8].js', // 1. 打包后的文件 2. 每次修改产生新的文件,放置覆盖 
    path: path.resolve(__dirname, 'build'), // 路径必须是一个绝对路径
    publicPath: 'http://localhost...'
  },
  1. 只给图片添加前缀 publicPath,给某一个资源添加cdn
      {
        test: /\.(png|jpg|jpeg|gif)$/,
        use:{
          loader: 'url-loader',
          options:{
            limit: 1,
            publicPath: 'http://localhost/img'
          }
        }
      },

package.json

{
  "name": "webpack4",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "build": "webpack --config webpack.config.js",
    "dev": "webpack-dev-server"
  },
  "devDependencies": {
    "@babel/core": "^7.4.5",
    "@babel/plugin-proposal-class-properties": "^7.4.4",
    "@babel/plugin-proposal-decorators": "^7.4.4",
    "@babel/preset-env": "^7.4.5",
    "autoprefixer": "^9.6.0",
    "babel-loader": "^8.0.6",
    "css-loader": "^3.0.0",
    "expose-loader": "^0.7.5",
    "file-loader": "^4.0.0",
    "html-webpack-plugin": "^3.2.0",
    "html-withimg-loader": "^0.1.16",
    "jquery": "^3.4.1",
    "less": "^3.9.0",
    "less-loader": "^5.0.0",
    "mini-css-extract-plugin": "^0.7.0",
    "postcss-loader": "^3.0.0",
    "style-loader": "^0.23.1",
    "url-loader": "^2.0.1",
    "webpack": "^4.35.2",
    "webpack-cli": "^3.3.5",
    "webpack-dev-server": "^3.7.2"
  },
  "dependencies": {
    "@babel/plugin-transform-runtime": "^7.4.4",
    "@babel/polyfill": "^7.4.4",
    "@babel/runtime": "^7.4.5"
  }
}

webpack.config.js

let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');
let MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
  mode: 'development', // 模式 默认两种 production development
  entry: './src/index.js', // 入口
  output: {
    filename: 'bundle.[hash:8].js', // 1. 打包后的文件 2. 每次修改产生新的文件,放置覆盖 
    path: path.resolve(__dirname, 'build'), // 路径必须是一个绝对路径
    // publicPath: 'http://localhost'
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      filename: 'index.html',
      minify: { // 压缩html
        removeAttributeQuotes: true, // 删除html双引号
        collapseWhitespace: true // html变成一行
      },
      hash: true // 设置hash戳
    }),
    new MiniCssExtractPlugin({
      filename: 'css/main.css'
    }),
  ],
  module: { // 模块
    rules: [ // 规则
      {
        test: /\.html$/,
        loader: 'html-withimg-loader'
      },
      {
        test: /\.(png|jpg|jpeg|gif)$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 1,
            outputPath: 'img/',
            // publicPath: 'http://localhost/img'
          }
        }
      },
      {
        test: /\.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [ // 预设
              '@babel/preset-env'
            ],
            plugins: [
              ["@babel/plugin-proposal-decorators", { "legacy": true }],
              ["@babel/plugin-proposal-class-properties", { "loose": true }],
              "@babel/plugin-transform-runtime"
            ]
          }
        },
        include: path.resolve(__dirname, 'src'),
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader'
        ]
      },
      {
        test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'less-loader'
        ]
      }
    ]
  }
}