初学者——webpack

102 阅读6分钟

英文文档:webpack.js.org/

中文文档:webpack.docschina.org/concepts/

一、webpack相关概念

  • 什么是webpack

    • Webpack是一个模块打包器——构建工具

      • 浏览器只认识html、js、css;其他的像less,是不认识的,所以需要构建工具处理成浏览器认识的文件
    • 在Webpack看来, 前端的所有资源文件(js、json、css、im、less...)都会作为模块处理

    • 它将根据模块的依赖关系进行静态分析,生成对应的静态资源

  • 核心内容

    • 默认配置文件

      • webpack.config.js : 是一个node模块,返回一个 json 格式的配置信息对象
    • entry:入口文件,指示 webpack 从哪个文件开始来作为构建其内部依赖图的开始;可以是字符串也可以是数组或者对象

    • output:指示webpack将打包好的文件输出到哪个文件以及如何命名

    • loader:loader 让 webpack 能够去处理那些非 JavaScript 、json文件

      • webpack 自身只能解析: JavaScript、json,可以解析部分es6语法,比如es6的模块化,但是像promise等语法是不能解析的

      • webpack官方出品,所以比较规范,一般以 xxx-loader 的方式命名,xxx 代表了这个 loader 要做的转换功能

      • Loader 本身也是运行在 node.js 环境中的 JavaScript 模块(可以自己使用node.js开发loader)

      • 它本身是一个函数,接受源文件作为参数,返回转换的结果

    • plugins:插件则可以用于执行范围更广的任务,如压缩、优化等

      • Plugins来自很多优秀程序员,所以命名不是那么规范

      • CleanWebpackPlugin: 自动清除指定文件夹资源

      • HtmlWebpackPlugin: 自动生成HTML文件并

      • UglifyJSPlugin: 压缩js文件

      • .....

    • mode:模式,用于指定开发环境还是生产环境

      • development——开发环境

      • production——生产环境

      • 生产环境会压缩代码

二、webpack的基本使用

  • 源代码一般放到src,打包之后的代码一般放到dist或者build

    • 源码里面一般有这几个文件夹js、html、json、imgaes等
  • webpack基于node(node必须10以上)

  • 先让我们的代码变成一个包管理项目

    • npm init
  • 安装webpack和webpack-cli

    • 需要全局安装和局部安装

    • npm i webpack webpack-cli -g

    • npm i webpack webpack-cli -D

  • 可以使用webpack进行工作了

    • 使用es6的模块化暴露和引入文件(es6的模块化浏览器是不认识的)

    • 使用命令webpack src/js/index.js -o dist/index.js --mode=development

    • 将src下的js下的index.js打包输出为dist文件夹下的index.js

  • webpack的基本功能是可以编译和打包js和json文件,能够将es6的模块语法转化成浏览器可以识别的语法,能压缩代码(在production模式下自动压缩)

三、使用webpack配置文件

  • 每次输入一长串命令很麻烦

  • 执行webpack命令时,会在当前目录查找webpack.config.js文件读取配置

  • 通过Commonjs暴露出去一个对象,里面可以配制参数,一般有以下几个参数

    • entry:入口文件,将所有打包资源全部引入

    • output:输出,将资源输出到指定目录下

    • loader:处理webpack不能够解析的模块

    • plugins:执行loader做不了的任务

    • mode:打包模式

  • 可以在package.json里面指定短命令

    • 在script对象中用key值代替val值中要执行的命令,使用时用npm run key值

四、使用loader解析less文件(使用less-loader)

  • 在使用less-loader的时候必须要less、css-loader、style-loader

    • less-loader是将less转换成css
    • css-loader是将css以CommonJs语法打包到js中
    • style-loader创建一个style标签,将js中的css放入其中
  • 安装less-loader、css-loader

    • npm i less less-loader css-loader style-loader -D

      • 默认都安装最新版本的,可能会报错,可以降低版本试试
      • 使用npm view less-loader versions查看当前less-loader有哪些版本
      • 使用npm view less-loader@5.0.0 peerDependencies查看当前版本需要哪个版本以上的webpack
      • 使用npm install less-loader@5.0.0 --save-dev

五、js语法检查(eslint eslint-loader)

  • 安装eslint eslint-loader

    • npm i eslint eslint-loader -D
  • 配置loader

    • eslint规则有两种方式
      • 配置loader的options规则里面(还在报错,待解决....)
        • 使用formatter引入外部资源
        • 外部资源为当前路径下.eslintrc命名的文件
      • 配置到package.json中
        • loader配置中的options选项不写
        • 在package.json中追加配置eslintConfig
"eslintConfig": {
    "parserOptions": {
      "ecmaVersion": 6,//支持es6语法
      "sourceType": "module" //支持模块化引入
    },
    "env": {// 支持的运行环境
      "browser": true, // 浏览器环境
      "node": true //node环境
    },
    "globals": {//可以使用的全局变量
      "$": "readonly",
      "Promise": "readonly"
    },
    "rules": {// 一些自定义规则
      "no-console": 0,
      "eqeqeq": 2,
      "no-alert": 2
    },
    // 扩展,值为 "eslint:recommended" 的 extends 属性启用一系列核心规则
    "extends": "eslint:recommended"
}
{
  text:/.js$/,
  exclude: /node_modules/,  //排除node_modules文件夹
  enforce: "pre",  //提前加载使用
  use: ['eslint-loader'],
  // 可以在这里配置eslint的规则,但是一般不在这里配置,
  // 可以配置在package.json中,也可以使用单独的文件配置
  options: {
      formatter: require('eslint-friendly-formatter')
  }
}

六、js语法转换和兼容性处理

  • 使用babel将es6转换为es5
  • 安装babel-loader

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

{
  test:/.js$/,
  exclude: /node_modules/,
  use: {
      loader: 'babel-loader',
      options: {
          presets: ['@babel/preset-env']
      }
  }
}
  • 缺点

    • 只能转换简单的es6语法,如let、const、箭头函数

    • 不能转换promise等

  • 转换更多的es6语法

    • 使用babel-polyfill

      • 包含ES6的高级语法的转换,不管编码人员用了哪些新语法,全部的新语法都转换
      • 安装:npm i babel-polyfill -D
      • 在入口文件直接引入就可以
      • import 'babel-polyfill'
      • 还没有写啥呢打包完就四百多KB
    • 使用core-js

      • 按需转换,使用了啥转换啥
      • 安装core-js
        • npm i core-js -D
      • 在bable-loader的基础上追加配置
{
    test:/.js$/,
    exclude: /node_modules/,
    use: {
        loader: 'babel-loader',
        options: {
            presets: [
                [
                    '@babel/preset-env',
                    {
                        useBuiltIns: 'usage',  // 按需引入需要使用polyfill
                        corejs: { version: 3 }, // 解决不能够找到core-js的问题
                        targets: { // 指定兼容性处理哪些浏览器
                            "chrome": "58",
                            "ie": "9"
                        }
                    }
                ]
            ]
        }
    }
}

七、url-loader处理图片资源&base64

  • 使用url-loader就不使用file-loader
  • 安装:npm install url-loader -D
  • 配置:

{
        test: /.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader'//不做图片转base64,可以用file-loader
            options: {
              limit: 8192,          
              outputPath:'img',         //图片最终输出的位置
              publicPath:'../build/img',//css资源图片路径
              name:'[hash:5].[ext]'     //修改图片名称
            }
          }
        ]
      }

八、html文件的处理(生成html文件)

  • 想让webpack自动的帮我们创建一个html
  • 然后把我们想要引入的东西引入进来,所以要借助插件
  • 安装插件:
    • npm i html-webpack-plugin -D
  • 引入插件:const HtmlWebpackPlugin = require('html-webpack-plugin');
  • 使用插件:

new HtmlWebpackPlugin({
    template: './src/index.html', // 以当前文件为模板创建新的HtML
    minify: {
        removeComments: true, //移除注释
        collapseWhitespace: true, //折叠所有留百
        removeRedundantAttributes: true, //移除无用的标签
        useShortDoctype: true,//使用短的文档声明
        removeEmptyAttributes: true,//移除空标签
        removeStyleLinkTypeAttributes: true,//移除rel="stylesheet"
        keepClosingSlash: true,//自结束
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true,
    }
})

九、使用html-loader处理html文件中的外部资源

  • 在html中引入图片或者其他资源,打包之后引用地址不对
  • 安装:html-loader
  • 使用:

{
    test: /.(html)$/,
    use: {
        loader: 'html-loader'
    }
}
  • 在这里要特别注意,到目前为止如果打包,那么html中的img的src依然是不正确的
  • 需要在url-loader中追加参数esModule:false

{
    test: /.(png|jpg|gif)$/i,
    loader: 'url-loader',       //如果不做图片转base64,可以用file-loader
    options: {
        limit: 8192,          // 小于这么多M的自己转base64
        outputPath:'images',         //图片最终输出的位置
        publicPath:'./images/', //css资源图片路径
        name:'[hash:4].[ext]',     //修改图片名称
        esModule:false
    }
}

十、file-loader处理其他资源,如字体图标

  • 安装:npm install file-loader --save-dev
  • 配置

{
    test: /.(eot|svg|woff|woff2|ttf|mp3|mp4|avi)$/,  // 处理其他资源
    loader: 'file-loader',
    options: {
      outputPath: 'media',
      name: '[hash:5].[ext]'
    }
}

十一、使用插件提取css,合并为单独的文件

  • 安装MiniCssExtractPlugin插件:npm i mini-css-extract-plugin -D
  • 使用插件

new MiniCssExtractPlugin({
    filename: "css/[name].css" //指定生成文件的目录和名字
})
  • 在less-loader中不需要创建style标签

{
    test:/.less$/,
    // use数组中loader执行顺序:从右到左,从下到上 依次执行
    use:[
        MiniCssExtractPlugin.loader, //单独提取出一个css文件
        // 'style-loader',// 创建style标签,添加上js中的css代码
        'css-loader',// 将css以commonjs方式整合到js文件中
        'less-loader'// 将less文件解析成css
    ]
}

十二、拆分prod配置文件和dev配置文件

  • 当前目录下新建config文件夹
  • 移动webpack.config.js文件到config中,改名为:webpack.prod.js
  • 通过执行:webpack --display-modules --config ./config/webpack.prod.js 指定配置文件运行

    • 这里需要将output配置路径修改为

prinft()

path:resolve(__dirname,'../dist')
  • 命令太长,我们可以在package.json里面的script配置短命令

"start": "webpack-dev-server --config ./config/webpack.dev.js",
"build": "webpack --config ./config/webpack.prod.js"
  • webpack.dev.js同理

十三、在开发环境中配置自动化编译

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

//配置自动化编译
devServer: {
  open: true, // 自动打开浏览器
  compress: true, // 启动gzip压缩
  port: 3000, // 端口号
  hot:true //开启热模替换功能 HMR
}
  • 当前的自动化更新不能及时更新html和css
  • 在入口文件配置中增加一个html的入口文件将会监听到html的变化

entry:['./src/js/index.js','./src/index.html']
  • css文件打包引入使用的是插件,所以监听不了,需要改用loader
    要配置一个完美的生态环境还远远不够........