webpack 4 基础知识点梳理

webpack安装

项目内安装

npm install webpack webpack-cli --save-dev
npx webpack -v // 查询版本
npm info webpack // 查看webpack的历史发布信息
npm install webpack@x.xx webpack-cli -D // 安装指定版本

webpack配置文件

默认配置文件 webpack.config.js

不使用默认的配置文件,例如想用 webpackconfig.js作为配置文件并执行

npx webpack --config webpackconfig.js

修改package.json字段

"scripts":{
  	"bundle": "webpack" // 这里不加npx,因为npm run执行的命令,会优先使用项目工程里的包,效果和npx类似
}

webpack核心概念

entry

指定打包入口文件

output

打包后的文件位置

loader

webpack默认只知道如何处理js模块,其他格式如css、图片等进行模块处理就需要用loader了
loader执行顺序:从右到左,从下到上

    // webpack.config.js
    ...
    module: {
        rules: [
          {
            test: /\.(png|jpe?g|gif)$/,
            use: {
              loader: 'file-loader',
              options: {
                name: '[name]_[hash].[ext]',
                outputPath:'images/'
              }
            }
          }
        ]
      }
      ...

file-loader

npm install file-loader -D
处理静态资源模块,它做的事情就是把打包入口中识别出的资源模块,移动到输出目录,并且返回一个地址名称。
使用场景:txt、svg、csv、excel、图片等

url-loader

  • npm install url-loader -D
  • 可以处理file-loader能够处理的所有事情,但是遇到jpg格式的模块,会把该图片转换成base64格式字符串,并打包到js里。对小体积的图片比较合适,对大图片不合适。
  • 缺点:增加打包后的js的体积,用户的加载速度会变慢

css-loader & style-loader

  • npm sintall style-loader css-loader -D

  • 它能分析css模块之间的关系,并合成一个css

  • style-loader会把css-loader生成的内容,以style挂载到页面的header部分

  module: {
      rules: [
        ...
        {
          test: /\.css$/,
          use: ["style-loader", "css-loader", "postcss-loader"]
        },
        ...
      ]
    },

sass-loader

  • npm instal sass-loader node-sass -D

  • sass-loader把sass语法转换成css,依赖node-sass模块

  {
     test: /\.scss$/,
     use: ["style-loader", "css-loader", "sass-loader"]
  }

stylus-loader

postcss-loader

  • npm install post-loader autoprefixer -D
  {
     test: /\.css$/,
     use: ["style-loader", "css-loader", "postcss-loader"]
  },
  • 新建post.config.js
  module.exports = {
    plugins: [require("autoprefixer")]
  };

plugins

html-webpack-plugin

  • npm install -D html-webpack-plugin
  • 它会在打包结束后,自动生成一个html文件,并把打包生成的js模块引入到该html中

clean-webpack-plugin

  • npm install -D clean-webpack-plugin
  • 在打包前都会清除之前的文件,生成新的带有hash值的文件
// webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const webpack = require("webpack");
module.exports = {
  ...
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: "html 模板",
      template: "./index.html"
    }),
		...
  ],
  ...
};

mini-css-exract-plugin

  • 现在css都是放在style里,这个插件可以抽离css成独立的文件
  		module: {
        rules: [
          {
            test: /\.css$/,
            use: [
                MiniCssExtractPlugin.loader,
                "css-loader"
            ]
          }
        ]
         }

CommonsChunkPlugin

  • https://www.webpackjs.com/plugins/commons-chunk-plugin/
  • 多页面打包时,可以拆出公共的模块
  • 通过将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,便存到缓存中供后续使用。这个带来速度上的提升,因为浏览器会迅速将公共的代码从缓存中取出来,而不是每次访问一个新页面时,再去加载一个更大的文件。

sourceMap

  • 源代码与打包后的代码的映射关闭

  • 在dev模式下默认开启,可以在配置文件中设置关闭

  devtool: "none"

webpack-dev-server

  • 提升开发效率的神器,修改完代码之后不再需要重新打包、刷新浏览器

  • 启动服务后,会发现dist目录没有了,这是因为dev-server不会把打包后的模块放在dist目录下,而是放在内存中,提升速度

  • npm install webpack-dev-server -D

  // package.json
  "scripts": {
      "server": "webpack-dev-server",
  		...
  }
    
  // webpack.config.js
  ...
  devServer: {
      contentBase: "./dist",
      open: true,
      hot: true,
      hotOnly: true
  },
  ...

跨域 & proxy

  • 主要用于开发环境接口联调,上线之后解决跨域可以用nginx转发

  • 创建server.js,启动一个服务器,mock一个接口

  • npm i express axios -D

  // package.json
  "scripts": {
      "server": "webpack-dev-server",
      "mock": "node server.js"
  },
  
  // server.js
  const express = require("express");
  const app = express();
  app.get("/api/info", (req, res) => {
    res.json({
      name: "xbl",
      age: 18,
      msg: "hello,xbl"
    });
  });
  
  app.listen("9092");
  • 项目中安装axios
  import axios from "axios";
  axios.get("/api/info").then(res => {
     console.log(res);
  });
  • 修改webpack.config.js设置服务器代理
  ...
  devServer: {
      proxy: {
        "/api": {
           target: "http://localhost:9092"
        }
      }
  },
  ...

HMR 热模块替换

  • hot module replacement

  • 需要使用module.hot.accept来观察模块更新,从而更新

  • 头部引入webpack

  // webpack.config.js
  
  const webpack = require("webpack");
  ...
  devServer: {
      contentBase: "./dist",
      open: true,
      hot: true,
      hotOnly: true
  },
  ...
  
  // 插件出添加
  plugins: [
      new CleanWebpackPlugin(),
      new HtmlWebpackPlugin({
        title: "html 模板",
        template: "./index.html"
      }),
      new webpack.HotModuleReplacementPlugin()
  ],

Babel处理ES6

babel-loader

  • babel-loader是webpack与babel的通信桥梁,不会做把es6转成es5的工作,这部分需要@babel/preset-env来做

@babel/core

  • Babel compiler core.

@babel/preset-env

  • npm i babel-loader @babel/core @babel/preset-env -D

  • @babel/preset-env中包含了es6转es5的转换规则

  const arr = [new Promise(() => {}), new Promise(() => {})];
  arr.map(item => {
    console.log(item);
  });
  • 以上几步还不够,Promise没有转换过来,这就需要借助 @babel/polyfill,把es的新特性都装进来,来弥补低版本浏览器中缺失的特性

@babel/polyfill

  • npm install --save @babel/polyfill
  // webpack.config.js
  {
      test: /\.js$/,
      exclude: /node_modules/,
      loader: "babel-loader",
      options:{
         presets:["@babel/preset-env"]
      }
  },
    
  // index.js
  import "@babel/polyfill"
  • 此时会发现打包的体积大了很多,这是因为polyfill默认会把所有特性注入进来,如何做到只注入用到的特性呢?
  ...		
  			{
          test: /\.js$/,
          exclude: /node_modules/,
          loader: "babel-loader",
          options:{
            presets:[
              ["@babel/preset-env",
                {
                  targets:{
                    edge:"17",
                    firefox:"60",
                    chrome:"67",
                    safari:"11.1"
                  },
                  useBuildtIns:"usage"
                }
              ]
            ]
          }
        },
  ...
  • 当我们开发的是组件库,工具库这些场景的时候,polyfill就不适合了,因为polyfill注入到全局变量中,会污染全局变量,所以推荐闭包的方式:@babel/plugin-transform-runtime

@babel/plugin-transform-runtime

  • npm i -D @babel/plugin-transform-runtime

  • npm i -S @babel/runtime

  • 使用方法

    • index.js中不需要再引入polyfill
    // import "@babel/polyfill"
  • 修改配置文件,注释掉之前的presets,添加plugins
      plugins: [
      		...
        [
          "@babel/plugin-transform-runtime",
          {
            "absoluteRuntime": false,
            "corejs": 2,
            "helpers": true,
            "regenerator": true,
            "useESModules": false
          }
        ]
        ...
      ],
  • babelrc文件

    • 可以用.babelrc文件代替以上plugins中的配置

    • 新建.babelrc文件

    // .babelrc
    {
      plugins: [
        [
          "@babel/plugin-transform-runtime",
          {
            "absoluteRuntime": false,
            "corejs": 2,
            "helpers": true,
            "regenerator": true,
            "useESModules": false
          }
        ]
      ]
    }
    
    // webpack.config.js
    {
       test: /\.js$/,
       exclude: /node_modules/,
       loader: "babel-loader"
    },

配置React打包环境

安装react

npm install react react-dom --save

编写react代码

// index.js
import "@babel/polyfill";

import React, { Component } from "react";
import ReactDom from "react-dom";

class App extends Component {
  render() {
    return <div>hello world</div>;
  }
}

ReactDom.render(<App />, document.getElementById("app"));

安装插件

  • 安装babel与react转换的插件

  • npm install -D @babel/preset-react

  • 新建babelrc文件

  {
    "presets": [["@babel/preset-env"], "@babel/preset-react"]
  }

配置vue打包环境

  • npm i -D vue vue-loader vue-template-compiler

  • 使用vue-loader解析.vue文件,template-compiler解析模板

  {
  		test: /\.vue$/,
      loader: "vue-loader"
  },
  ...
  plugins:[
      new VueLoaderPlugin()
  ]
  • 这个插件是将你定义过的其他规则复制并应用到.vue文件里相应语言的块。例如,如果你有一条匹配规则/\.js$/的规则,那么它会应用到.vue文件里的<script>
posted @ 2019-05-06 14:56  dora_zc  阅读(467)  评论(0编辑  收藏  举报