Webpack教程~保姆级入门篇

基础概念

官网安装方式css

经过官网的指引安装好webpack,在项目根目录添加 webpack.config.js 的文件. webpack.config.js 遵循的是 commonJS 规范,依次文件采用 module.exports={[key]:[value]} 的方式,来暴露具体的配置。html

一个基本的webpack配置以下node

module.exports = {
  entry: "[xxx].js",
  output: {
    filename: 'xxxx.js',
    path: resolve(__dirname, 'xxx')
  },
  module: {
    rules: [
      {[key]:[value]}
    ]
  },
  plugins: [
    new PluginsName()
  ],
  mode: 'production | development'
}
复制代码

官网基础概念webpack

Entry

指定webpack,打包的起始文件,根据此文件分析构建依赖关系图。git

入口文件,可配置一个,也能够 {[key]:[value]} 的形式配置多个es6

Output

指示webpack打包后的资源,输出到哪里去,以及如何命名。github

output的值是一个对象,指定了输出文件名,和文件路径,输出文件建议使用 path模块中的resolve即 resolve(__dirname,xxx)web

在webpack中输出的文件名,若是你不想指定,能够取使用[hash].扩展名的形式,webpack在输出的时候,会自动指定hash值。面试

Loader

Webpack去处理那些非Javascript文件。(webpack自己只处理js和json数据)正则表达式

对应webpack的字段是 module,里面指定了webpack各类的loader配置。形如

module: {
    rules: [
      {[key]:[value]}
    ]
  },
复制代码

rules中的每个对象,对应着一个处理某个文件的模块,为了处理某种文件,咱们须要配置,匹配这个文件的正则表达式,形如 test:/具体正则表达式/ ,和经过 use:[loader-name] 的形式指定 多个loader,如:处理css 文件,咱们须要 style-loadercss-loader 。甚至有时候use数组里面,不仅是 各个loader的名称,可能还须要修改一些loader的配置,就会采起对象的形式指定loader,如给css添加兼容性处理的情景

同一文件各类loader的处理顺序是自下而上的,css文件配置以下,文件会先通过 css-loader 处理,再通过style-loader处理。

module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
        ]
      }
    ]
  },
复制代码

上面引入的两种loader都是直接经过loader名称的形式引入的,按照对象的方式引入postcss-loader,对css作兼容性处理。

{
    test: /\.css$/,
    use: [
      'style-loader'
      'css-loader',
      {
        loader: 'postcss-loader',
        options: {
          ident: 'postcss',
          plugins: () => {
            require('postcss-preset-env')
          }
        }
      }
    ]
  },
复制代码

固然最后要注意的是,这些loader都不是webpack,内置的,而是须要 经过npm 安装。具体的插件安装可看官网。建议你们和webpack有关的都安装在 devDependencies 下 。

Plugins

各类功能强大的工具,包括打包优化和压缩,甚至能够从新定义环境中的变量。插件相比于Loader能够作不少比Loader功能更强大的事。

插件和loader相同的是都须要先npm安装,不一样的是,loader不须要引入,可是要在use里面写一些配置。而插件则是经过,先require 引入某个插件,而后再在plugins,实例化引入的插件对象便可。若是须要修改插件的默认配置,在实例化的时候,以对象的形式传入便可。

html 模板插件使用以下

const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  entry: '......',
  output:'......',
  module:'......',
  plugins: [
    // 实例化require引入的插件 html-webpack-plugin
    //指定传入的HTML模板是src目录下的index.html文件
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: '.....'
}
复制代码

Mode

模式分为 development开发环境,production 生产环境。 这大概是webpack最简洁的配置了,在production 模式下,会自动开启压缩js代码和 tree shaking

在将来的 webpack5中,只有在 webpack.config.js 文件中指定一个mode,就可使用,上面的 entry,output 等配置,都变成了默认配置。

webpack打包过程

  1. 指定入口文件 entry
  2. webpack会根据入口文件里面全部的依赖,造成依赖树,而后会根据依赖树中把因此须要的依赖引入,造成代码块(chunk),而后再根据不一样的资源对应的loader,对代码块进行处理输出为 bundles.

处理css、less

npm install style-loader css-loader  -D
复制代码

其中 css-loader 是为了把 css 文件变成commonJS模块,加载到JS中,style-loader是为了在JS解析的时候能建立style标签,把样式整合到style标签中,插入浏览器的head。

默认是有多少css,less 文件就会插入多少style标签,每一个标签就是对应的css代码。

npm install less-loader -D 
复制代码

安装less-loader处理less文件,注意loader在代码里面配置顺序是固定的,less文件必需要通过less-loader处理,才能被css-loader识别,同理最后才能被style-loader处理。

rules: [
      {
        test: /\.css$/,
        use: [
          // 从下到上运行loader
          // 建立style标签,将js资源插入,添加到head生效
          'style-loader',
          // 将css 文件变成commonjs 模块加载到js中,里面内容 是样式字符串。
          'css-loader',
        ]
      },
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          'less-loader'
        ]
      }
    ]
复制代码

把css,less文件提取合并,而且压缩一下造成单独的css,再经过link标签引入。目的是为了把css尽快的提供给浏览器,而不是放在js中,致使浏览器须要先解析js才能获取css,具体缘由见博客~浏览器,须要使用插件 mini-css-extract-plugin

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
复制代码

把css文件和less文件配置中的,style-loader都替换成 MiniCssExtractPlugin.loader,在plugins中实例化插件而且制定输出文件路径,完整配置以下

const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: 'js/build.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ]
      },
      {
        test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/public/index.html'
    }),
    // [hash:10]制定文件名称取哈希值的前10位
    new MiniCssExtractPlugin({
      filename:"css/[hash:10].css"
    })
  ],
  mode: 'development'
}
复制代码

压缩css,感受就是去掉了css文件中的,空格注释,也可能去掉了一些写重复的样式吧,反正就是为了减小文件体积加快网络传输速度。须要用到插件optimize-css-assets-webpack-plugin

npm install optimize-css-assets-webpack-plugin -D
复制代码

这个插件使用比较简单了,同样须要引入

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')

....
  plugins: [
    ....,
    new OptimizeCssAssetsWebpackPlugin()
  ]
.... 
复制代码

处理HTML、图片、其余静态资源

npm install html-webpack-plugin -D
复制代码

处理HTML文件须要使用 html-webpack-plugin,在plugins中实例化的时候,指定一下使用的模板,webpack会把输出的js经过script标签自动引入HTML中。

// webpack处理 HTML
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: '/js/build.js',
    path: resolve(__dirname, 'build')
  },
  module: {
  },
  plugins: [
    new HtmlWebpackPlugin({
      //指定 src下的index.html 为HTML基础模板。
      template: './src/index.html'
    })
  ],
  mode: 'development'
}
复制代码

处理图片资源的时候使用的是loader名称是url-loader,没有photo-loader😁😁😁,固然还要下载file-loader,由于url-loader依赖于file-loader

npm install file-loader url-loader -D
复制代码

具体配置以下,能够解决commonJS import 图片资源,和css,less文件中url里面引用图片资源的问题。

{
  test: /\.(jpg|png|gif|jpeg)$/,
  loader: 'url-loader',
  options: {
    // 图片小于8kb时候会被base64处理
    limit: 8 * 1024,
    // 给图片从新命名
    // ext 图片原来扩展名称
    name:'[hash:10].[ext]'
  }
},
复制代码

若是还要处理HTML模板中引入图片的问题还须要使用 html-loader, 此时要注意修改一下以前url-loader的配置,由于url-loader默认使用es6模块化解析,而html-loader引入图片是commonjs,解析时会出问题:[object Module],须要在url-loader配置文件中,关闭url-loader的es6模块化,使用commonjs解析

npm install html-loader -D
复制代码
{
  test: /\.(jpg|png|gif|jpeg)$/,
  loader: 'url-loader',
  options: {
    limit: 8 * 1024,
    // 解决:关闭url-loader的es6模块化,使用commonjs解析
    esModule: false,
    name:'[hash:10].[ext]'
  },

},
{
  test: /\.html$/,
  loader: 'html-loader'
}
复制代码

处理其余静态资源,好比字体图标文件等,须要安装file-loader,在以前安装url-loader的时候已经安装过file-loader了

{
   // exclude 排除 前面被处理过的 css/js/html资源
   // 其余文件一概交给file-loader处理。
  exclude: /\.(css|js|html|less)$/,
  loader: 'file-loader',
  options: {
    name: '[hash:10].[ext]',
    // 指定其余资源都输出到static目录下
    outputPath: 'static'
  }
}
复制代码

css兼容性处理

面试的时候常常会被问到,浏览器兼容性问题,做为一个学生,目前我开发都是使用Chrome和Firefox,处理浏览器兼容性问题,也就是webpack配置一下。 兼容css须要用插件postcss-loader,和插件的的配置postcss-preset-env(固然也可采用,autoprefixer规则取代postcss-preset-env规则)

npm install postcss-loader postcss-preset-env -D
复制代码

安装好插件,若是业务场景浏览器肯定,可采用中 package.json 增长browserslist,来肯定具体浏览器,至于browserslist的配置文件可看github

其中development,production 是指NodeJS环境(process.env.NODE_ENV),默认是production,而非webpack指定的mode。

{
  "xxx":"xxx",
  "devDependencies": "xxxx",
  "browserslist": {
    "development": [
      "last 1 version",
      "> 1%",
      "IE 10"
    ],
    "production": [
      "> 0.2%",
      "not dead",
      "not op_mini all"
    ]
  }
}
复制代码

具体配置以下

const miniCssExtractPlugin = require('mini-css-extract-plugin')
//指定node环境为 development
process.env.NODE_ENV = 'development'
module.exports = {
  entry: "...",
  output: "....",
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          miniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: (loader) => [
                //也能够采用
                // require('postcss-preset-env')()
                require('autoprefixer')()
              ]
            }
          }
        ]
      },
    ]
  },
  plugins:".....",
  mode: '.....'
}
复制代码

devServer

配置devServer,至关于本地运行了一个NodeJS后来服务,须要安装插件webpack-dev-server,此时webpack编译的结果不会输出在咱们指定的目录下,由于dev-server不输出文件,能够想象成文件放内存中,node服务能够访问到,所以咱们手动刷新浏览器能够看到正确结果。

npm install webpack-dev-server -D
复制代码
module.exports = {
  ....,
  mode: '.....',
  devServer: {
    // 项目构建后路径
    contentBase: resolve(__dirname, 'build'),
    // 启动gzip压缩
    compress: true,
    // 端口号
    port: 3000,
    // 自动打开浏览器
    open: true
  }
};
复制代码

此时我建议在 package.jsonscript 脚本中写入两条脚本,分别用于以前的打包模式和开启devServer 模式

{
  ....,
  "scripts": {
    ....,
    "build": "webpack",
    "build:prod": "webpack --mode=production",
    "dev": "webpack-dev-server --open",
  },
  ....
}
复制代码

经过运行 npm run build 或者npm run build:prod 获取以前相似的输出,npm run dev 开启webpack服务,此时还不支持热更新和自动刷新浏览器,须要手动刷新,才能看到结果。

更多devServer看 官网配置

Javascript代码兼容性

前面配置了css代码的兼容性处理,可是JS代码其实更须要兼容,JS不兼容可能就是没法运行。处理JS兼容固然就是babel家族。babel官网

npm install @babel/cli @babel/core @babel/preset-env babel-loader -D

npm install @babel/plugin-transform-runtime  -D 

npm install @babel/plugin-proposal-class-properties -D

npm install @babel/runtime @babel/runtime-corejs2 --save
复制代码

在项目根目录编写 babel.config.js 文件,写入以下配置

module.exports = {
  "presets": [
       [
         "@babel/preset-env",
         //指定要兼容的浏览器,以及版本
         "targets": {
          "esmodules": true,
          "chrome": '60',
          "firefox": '60',
          "ie": '9',
          "safari": '10',
           "edge": '17'
          }
        ]
    ],
  "plugins": [
    ["@babel/plugin-transform-runtime", {
      "corejs": 2,
    }],
    "@babel/transform-arrow-functions",
    "@babel/plugin-proposal-class-properties"
  ]
}
复制代码

在webpack.config.js中用babel处理js

module.exports={
  entry:"....",
  output:"....",
  module:{
    rules:[
      { 
        // 匹配js和jsx文件
        test: /\.tsx?$/,
        use: ["babel-loader"],
        //排除node_modules里面的文件
        // 防止babel编译了,node_modules里面代码包。
        exclude: [join(__dirname, "node_modules")]
      }
    ]
  },
}

复制代码

上面的babel配置 (我用的是babel7的配置) 是我上次配置ts的,不知道会不会出错,应该没有问题, presets 里面指定了target, core-js 部分没问题,应该就能够兼容ie。

我认为 webpack最好的教程是来源与官网,这是我看了官网和网上找的一些视频教程以后总结的一些基础操做,详细的配置可看 webpack官网~中文,本文中部分文字来源于尚硅谷的视频,感谢尚硅谷老师的分享。【这不是广告只是为了声明版权😂】

以上差很少就是 webpack的一些基本操做了,后面打算把webpack配置优化部分也补上,而后本身封装一个脚手架,再加上一些ESLint的配置,欢迎你们持续关注 http://lemonlife.top 最近有点忙/(ㄒoㄒ)/~~

相关文章
相关标签/搜索