【Webpack】Webpack4.x 常用操作 | 案例 | 相关构建工具

版权声明:转载请注明出处!喜欢就 关注一下 or 右上角点赞 鼓励一下呗^_^ https://blog.csdn.net/ImagineCode/article/details/84142538

参考:中文文档:https://www.webpackjs.com/

在这里插入图片描述

1️⃣. 引入 | Demo

当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要(依赖)的每个模块(modules),然后将所有这些模块打包成一个或多个 assets。

在这里插入图片描述

操作 - 创建package.json文件

  • 1、创建一个webpack的项目根目录(如wptest),然后在根目录进行命令行操作:

npm init -y 初始化一个package.json文件

然后将webpack安装在本地 npm i -D webpack

注意:

  • 不推荐使用全局安装
  • 超过4.0的webpack版本,需要额外再安装一个webpack-cli 命令行工具

npm install --save-dev webpack

完成安装之后如下如所示:

在这里插入图片描述

  • 2、在根目录下方新建如下文件夹与文件(dist 、src、index.html、index.js):

在这里插入图片描述

扫描二维码关注公众号,回复: 4888865 查看本文章
  • 3、接着,我们做一些尝试:使用loadsh工具库写一个小测试:首先先安装 开发依赖 loadsh 工具库
    npm i lodash -P

lodash 参考:https://www.lodashjs.com/

然后在````index.js```文件中写如下代码:

import _ from 'lodash';

let createDomElement = ()=>{
    let dom = document.createElement('div');
    dom.innerHTML = _.join(['https://','blog','.csdn','.net','/imaginecode'],'');
    return dom;
}
document.body.appendChild(createDomElement());

接着,在index.html文件中写入:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Webpack App</title>
  <body>
  <script type="text/javascript" src="./main.js"></script>
  </body>
</html>

  • 4、在根目录下添加webpack.config.js,编写webpack.config.js文件

webpack.config.js遵循Nodejs

const path = require('path');
module.exports = {
 mode: 'development',
 entry: './src/index.js',
 output: {
 	filename: 'main.js',
 	path: path.resolve(__dirname,'./dist')
 }

}
  • 5、执行webpack npx webpack进行构建

你可以在package.json 的scripts下加入"build":"npx webpack"
以后就只需要执行 npm run build

在这里插入图片描述

执行成功后,然后我们在浏览器中打开index.html

在这里插入图片描述

2️⃣. 一些webpack概念

前面我们用一个小Case让大家了解了一下Webpack。下面,我们在开始进一步完善我们的Case前,需要先知道一些webpack的先验知识/概念。这些概念也可以在Case的进行中在https://www.webpackjs.com/中文文档中进行查阅。

npm 与 package.json

  • –save-dev 安装的 插件,被写入到 devDependencies 对象里面去
  • –save 安装的插件,被写入到 dependencies 对象里面去
  • devDependencies 里面的插件只用于开发环境,不用于生产环境
  • dependencies 是需要发布到生产环境(production)

webpack.config.js

配置大都是在导出的模块(module.exports)对象体中完成的:

module.exports = {

}
  • mode 开发模式
module.exports = {
	mode: 'production', //设置开发模式为生产模式
}
  • entry入口文件
module.exports = {
    mode: 'production',
    entry: { //入口文件
        app:'./src/index.js',
    },
 }

入口配置,告诉webpack应该从哪个模块开始(上面从src/index.js这个模块),作为构建内部依赖图的开始。可以配置多个

  • output 输出文件
module.exports = {
    mode: 'production',
    entry: {
        app:'./src/index.js',
        print:'./src/print.js'
    },
    output: { //输出文件
        filename: '[name].bundle.js',    //如何命名
        path:path.resolve(__dirname,'./dist') //在哪里输出bundles
    },

output属性,则是告诉webpack在哪里(path)输出它所创建的assets(或者说bundles),并告诉Webpack要怎样命名这些文件(filename)。

module 模块

module 模块中的选项决定了如何处理项目中不同类型的模块。

  • module.noParse :RegExp | [RegExp] | function

这项能防止webpack解析与给定的正则表达式相匹配的文件。需要注意的是,不进行解析的文件中不能含有import,require,define等其他导入机制。通常,我们可以选择不对大文件库进行解析,如jquery。

  • module.rules

rules,顾名思义,是一种规则数组。即,当创建模块时,根据规则数组进行匹配。同时,这些规则能够对模块应用loader等。

  • module.rules.test: Condition
    Condition一般提供一个正则表达式或者正则表达式数组RegExp | [RegExp]

同时还有其他条件,如:
{include:Condition} :匹配特定条件,一般是提供一个字符串或者字符串数组。
{exclude:Condition} :排除特定条件。一般是提供一个字符串或字符串数组。
{and: [Condition]} :必须匹配数组中的所有条件。
{ or: [Condition] }: 匹配数组中任何一个条件。
{ not: [Condition] }: 必须排除这个条件。

module: {
    rules: [
      {
        test: /\.css$/,
        include: [
          path.resolve(__dirname, "app/styles"),
          path.resolve(__dirname, "src/styles")
        ],
        use: ['style-loader', 'css-loader']
      }
    ]
  }
  • rules.use

告诉模块要使用哪个loader。若有多个loader的话,从右向左(从下到上)进行应用。

use: [
  'style-loader',
  {
    loader: 'css-loader',
    options: {
      sourceMap: true
    }
  },
  {
    loader: 'postcss-loader',
    options: {
      sourceMap: true
    }
  }
];
  • loader

原本,webpack是只能处理javascript文件的,但这样的话,岂不是很不爽?! 所以,loader来了,它能让webpack去处理非javascript文件
简单理解,loader将所有类型的文件(如css、scss、png、jpg、…等类型)进行转换,转换为webpack能处理的模块。
css-loader转换css文件 :
使用前先安装 npm i -D css-loader

module: {
rules: [
            {
              test: /\.css$/,
              use: [
                {
                  loader: 'css-loader',
                  options: {
                    sourceMap: true
                  }
                }
      ]
}
  • plugins 插件

如果将loader理解为转换某些类型的模块,那么plugins能处理的任务可不止这些。如打包、压缩,定义环境变量…插件能用来处理各种各样的任务。

在这里插入图片描述

3️⃣. 接着写小Case

加载CSS文件

  • 安装:使用style-loader(把js中引入的css内容注入到Html < style >标签中,其依赖css-loader) 和css-loader(解析js中import 的css文件)可以解析css和style
    npm i -D style-loader css-loader
  • 添加loader
const path = require('path');

module.exports = {
  entry: {
  	app:'./src/index.js',
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'] //从右向左应用到模块
      }
    ]
  }
};
  • 添加 /src/style.css
.c-red {color:red;}
  • index.js修改
import _ from 'lodash';
import './style.css'
let createDomElement = ()=>{
    let dom = document.createElement('div');
    dom.innerHTML = _.join(['https://','blog','.csdn','.net','/imaginecode'],'');
    dom.className = 'c-red';
    return dom;
}
document.body.appendChild(createDomElement());

加载sass(scss)文件 、配置sourceMao

  • 安装: npm i -D sass-loader node-sass webpack
  • 添加loader
module: {
	rules: [{
      test: /\.scss$/,
      use: [{
        loader: "style-loader"
      }, {
        loader: "css-loader",
        options: {
			sourceMap: true   //利于开发调式,定位文件
		}
      }, {
        loader: "sass-loader",
        options: {
			sourceMap: true
		}
      }]
    }]
}

添加PostCSS

postcss 可以利用为CSS3属性添加前缀的方式实现CSS的模块化,防止样式冲突。这也是常用的方式。 参考文档:https://postcss.org/

  • 安装:npm i -D postcss-loader autoprefixer
  • webpack.config.js 添加loader
...
const autoprefixer = require('autoprefixer');
...
module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              sourceMap: true
            }
          },
          {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              sourceMap: true,
              plugins: loader => [
                require('autoprefixer')({ browsers: ['> 0.15% in CN'] }) // 添加前缀
              ]
            }
          },
          {
            loader: 'sass-loader',
            options: {
              sourceMap: true
            }
          }
        ]
      }
    ]
  }

将样式输出为文件

注意:抽取样式后,就不会使用style-loader注入css到HTML了。

  • 安装: npm i -D mini-css-extract-plugin
  • 添加loader和plugins
...
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
...
module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          MiniCssExtractPlugin.loader, //抽取样式
          'css-loader',
          'postcss-loader',
          'sass-loader'
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename:  '[name].[hash].css', // 设置最终输出的文件名
      chunkFilename: '[id].[hash].css'
    })
  ]

此时,可以运行npm run build 或 npx webpack看结果

压缩css、Js

  • 安装: npm i -D optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin
  • 修改webpack.config.js :增加optimization
...
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
...
plugins:[
   ...
],
optimization: {
   minimizer: [
		new UglifyJsPlugin({
                cache: true,
                parallel: true,
                sourceMap: true 
             }),
   ],
   minimizer: [new OptimizeCSSAssetsPlugin({})]
}

将CSS文件和JS文件注入到HTML模板中

  • 安装: npm i -D html-webpack-plugin
  • 修改webpack.config.js
...
const HtmlWebpackPlugin = require('html-webpack-plugin');
...
plugins: [
    ...
    new HtmlWebpackPlugin({
      minify: { //压缩html配置,在development模式下先不进行压缩,到production下再进行
        collapseWhitespace: false,
        removeComments: false,
        removeAttributeQuotes: false // 移除属性的引号
      }
    })
  ],
optimization: {
...
}

清理dist目录

  • 安装:npm i -D clean-webpack-plugin
  • webpack.config.js
...
const CleanWebpackPlugin = require('clean-webpack-plugin');
...
let pathsToClean = [
    'dist/*.js',
    'dist/*.css',
    'dist/*jpg',
]
let cleanOptions = {
    root: '',
    exclude: ['index.html'],
    verbose: true,
    dry: false
}
plugins: [
    new CleanWebpackPlugin(pathsToClean,cleanOptions), //构建前清除dist文件夹
      ...
    ],

加载与优化图片和用base64编码图片

  • 安装 npm i -D file-loader image-webpack-loader url-loader
  • webpack.config.js
    module: {
          rules: [
            ...
            {
              test: /\.(png|svg|jpg|gif|jpeg|ico|woff|woff2|eot|ttf|otf)$/,
                    use: [
                        {
                            loader: 'url-loader', // 根据图片大小,把图片优化成base64
                            options: {
                              limit: 10000
                            }
                        },
                        {
                            loader: 'image-webpack-loader',// 先进行图片优化
                            options: {
                                name: 'dist/[name].[ext]',
                                
                                mozjepg:{
                                    progressive: true,
                                    quality: 65
    
                                },
                                optipng: {
                                    enabled: false,
                                },
                                pngquant: {
                                    quality: '65-90',
                                    speed: 4
                                },
                                gifsicle: {
                                    interlaced: false,
                                },
                                webp: {
                                    quality: 75
                                }
                            }
                        }
                    ]
           }
          ]
        }

查找源-辅助开发

  • 一般用在开发环境
  • 添加inline-source-map
module.exports = {
...
devtool: 'inline-source-map',
...
}

监控、热更新

  • 监控变化,执行命令:npx watch

  • 热更新

    • 安装: npm i -D webpack-dev-server
    • webpack.config.js
      module.exports = {
     		...
     		devServer: {
     			contentBase: './dist', //文件变化后,自动打包更新到dist目录
     			hot: true  //启用热更新
     		}
     		...
     }
    
    • 运行启动webserver:webpack-dev-server --open
    • devServer其他配置:
      参考文档
devServer: {
  clientLogLevel: 'warning', // 可能的值有 none, error, warning 或者 info(默认值)
  hot: true,  // 启用 webpack 的模块热替换特性, 这个需要配合: webpack.HotModuleReplacementPlugin插件
  contentBase:  path.join(__dirname, "dist"), // 告诉服务器从哪里提供内容, 默认情况下,将使用当前工作目录作为提供内容的目录
  compress: true, // 一切服务都启用gzip 压缩
  host: '0.0.0.0', // 指定使用一个 host。默认是 localhost。如果你希望服务器外部可访问 0.0.0.0
  port: 8080, // 端口
  open: true, // 是否打开浏览器
  overlay: {  // 出现错误或者警告的时候,是否覆盖页面线上错误消息。
    warnings: true,
    errors: true
  },
  publicPath: '/', // 此路径下的打包文件可在浏览器中访问。
  proxy: {  // 设置代理
    "/api": {  // 访问api开头的请求,会跳转到  下面的target配置
      target: "http://192.168.0.102:8080",
      pathRewrite: {"^/api" : "/mockjsdata/5/api"}
    }
  },
  quiet: true, // necessary for FriendlyErrorsPlugin. 启用 quiet 后,除了初始启动信息之外的任何内容都不会被打印到控制台。这也意味着来自 webpack 的错误或警告在控制台不可见。
  watchOptions: { // 监视文件相关的控制选项
    poll: true,   // webpack 使用文件系统(file system)获取文件改动的通知。在某些情况下,不会正常工作。例如,当使用 Network File System (NFS) 时。Vagrant 也有很多问题。在这些情况下,请使用轮询. poll: true。当然 poll也可以设置成毫秒数,比如:  poll: 1000
    ignored: /node_modules/, // 忽略监控的文件夹,正则
    aggregateTimeout: 300 // 默认值,当第一个文件更改,会在重新构建前增加延迟
  }
}

babel转码

  • 安装: npm i -D babel-loader babel-core babel-preset-env babel-plugin-transform-runtime babel-runtime
  • webpack.config.js
rules: [
    {
      test: /\.js$/,
      exclude: /(node_modules)/,  // 加快编译速度,不包含node_modules文件夹内容
      use: {
        loader: 'babel-loader'
      }
    }
  ]
  • 项目根目录添加.babelrc文件
{
	"presets": ["env"]
}

最后,你可以在index.js文件中写一些ES6语法运行试试。

在这里插入图片描述

4️⃣. 常用loader小结

文件

  • raw-loader 加载文件原始内容(utf-8)
  • val-loader 将代码作为模块执行,并将 exports 转为 JS 代码
  • url-loader 像 file loader 一样工作,但如果文件小于限制,可以返回 data URL
  • file-loader 将文件发送到输出文件夹,并返回(相对)URL

JSON

  • json-loader 加载 JSON 文件(默认包含)
  • json5-loader 加载和转译 JSON 5 文件
  • cson-loader 加载和转译 CSON 文件

转换编译

  • html-loader 导出 HTML 为字符串,需要引用静态资源
  • pug-loader 加载 Pug 模板并返回一个函数
  • jade-loader 加载 Jade 模板并返回一个函数
  • markdown-loader 将 Markdown 转译为 HTML
  • react-markdown-loader 使用 markdown-parse parser(解析器) 将 Markdown 编译为 React 组件
  • posthtml-loader 使用 PostHTML 加载并转换 HTML 文件
  • handlebars-loader 将 Handlebars 转移为 HTML
  • markup-inline-loader 将内联的 SVG/MathML 文件转换为 HTML。在应用于图标字体,或将 CSS 动画应用于 SVG 时非常有用。

样式

  • style-loader 将模块的导出作为样式添加到 DOM 中
  • css-loader 解析 CSS 文件后,使用 import 加载,并且返回 CSS 代码
  • less-loader 加载和转译 LESS 文件
  • sass-loader 加载和转译 SASS/SCSS 文件
  • postcss-loader 使用 PostCSS 加载和转译 CSS/SSS 文件
  • stylus-loader 加载和转译 Stylus 文件

清理和测试

  • mocha-loader 使用 mocha 测试(浏览器/NodeJS)
  • eslint-loader PreLoader,使用 ESLint 清理代码
  • jshint-loader PreLoader,使用 JSHint 清理代码
  • jscs-loader PreLoader,使用 JSCS 检查代码样式
  • coverjs-loader PreLoader,使用 CoverJS 确定测试覆盖率

框架

  • vue-loader加载和转译 Vue 组件
  • polymer-loader 使用选择预处理器(preprocessor)处理,并且 require()类似一等模块(first-class)的 Web 组件
  • angular2-template-loader 加载和转译 Angular 组件
  • Awesome 更多第三方 loader,查看 awesome-webpack 列表

5️⃣. 参考开发、生产环境配置

开发环境webpack.dev.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin');
const autoprefixer = require('autoprefixer');
const webpack = require('webpack');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, './dist')
  },
  devtool: 'inline-source-map',
  devServer: {
    clientLogLevel: 'warning', // 可能的值有 none, error, warning 或者 info(默认值)
    hot: true, // 启用 webpack 的模块热替换特性, 这个需要配合: webpack.HotModuleReplacementPlugin插件
    contentBase: path.join(__dirname, "dist"), // 告诉服务器从哪里提供内容, 默认情况下,将使用当前工作目录作为提供内容的目录
    compress: true, // 一切服务都启用gzip 压缩
    host: '0.0.0.0', // 指定使用一个 host。默认是 localhost。如果你希望服务器外部可访问 0.0.0.0
    port: 8085, // 端口
    open: true, // 是否打开浏览器
    overlay: { // 出现错误或者警告的时候,是否覆盖页面线上错误消息。
      warnings: true,
      errors: true
    },
    publicPath: '/', // 此路径下的打包文件可在浏览器中访问。
    proxy: { // 设置代理
      "/api": { // 访问api开头的请求,会跳转到  下面的target配置
        target: "http://192.168.0.102:8080",
        pathRewrite: {
          "^/api": "/mockjsdata/5/api"
        }
      }
    },
    quiet: true, // necessary for FriendlyErrorsPlugin. 启用 quiet 后,除了初始启动信息之外的任何内容都不会被打印到控制台。这也意味着来自 webpack 的错误或警告在控制台不可见。
    watchOptions: { // 监视文件相关的控制选项
      poll: true, // webpack 使用文件系统(file system)获取文件改动的通知。在某些情况下,不会正常工作。例如,当使用 Network File System (NFS) 时。Vagrant 也有很多问题。在这些情况下,请使用轮询. poll: true。当然 poll也可以设置成毫秒数,比如:  poll: 1000
      ignored: /node_modules/, // 忽略监控的文件夹,正则
      aggregateTimeout: 300 // 默认值,当第一个文件更改,会在重新构建前增加延迟
    }
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules)/, // 加快编译速度,不包含node_modules文件夹内容
        use: [{
          loader: 'babel-loader'
        },{
          loader: 'eslint-loader',
          options: {
            fix: true
          }
        }]
      },
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          'style-loader', {
            loader: 'css-loader',
            options: {
              sourceMap: true
            }
          }, {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              sourceMap: true,
              plugins: (loader) => [autoprefixer({browsers: ['> 0.15% in CN']})]
            }
          }, {
            loader: 'sass-loader',
            options: {
              sourceMap: true
            }
          }
        ]
      }, {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10000
            }
          }
        ]
      }, {
        test: /\.(png|svg|jpg|gif|jpeg|ico)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10000
            }
          }, {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
                quality: 65
              },
              optipng: {
                enabled: false
              },
              pngquant: {
                quality: '65-90',
                speed: 4
              },
              gifsicle: {
                interlaced: false
              },
              webp: {
                quality: 75
              }
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({filename: '[name].css', chunkFilename: '[id].css'}),
    new CleanWebpackPlugin(['dist']),
    new webpack.NamedModulesPlugin(), // 更容易查看(patch)的依赖
    new webpack.HotModuleReplacementPlugin(), // 替换插件
    new HtmlWebpackPlugin({
      minify: {
        collapseWhitespace: true,
        removeComments: true,
        removeAttributeQuotes: true, // 移除属性的引号
      },
      template: path.resolve(__dirname, 'src/index.html')
    })
  ],
  optimization: {}
};

生产环境webpack.prod.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin');
const autoprefixer = require('autoprefixer');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: 'main.[hash].js',
    path: path.resolve(__dirname, './dist')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules)/, // 加快编译速度,不包含node_modules文件夹内容
        use: [{
          loader: 'babel-loader'
        },{
          loader: 'eslint-loader',
          options: {
            fix: true
          }
        }]
      },
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          MiniCssExtractPlugin.loader, {
            loader: 'css-loader'
          }, {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              plugins: (loader) => [autoprefixer({browsers: ['> 0.15% in CN']})]
            }
          }, {
            loader: 'sass-loader'
          }
        ]
      }, {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10000
            }
          }
        ]
      }, {
        test: /\.(png|svg|jpg|gif|jpeg|ico)$/,
        use: [
          'file-loader', {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
                quality: 65
              },
              optipng: {
                enabled: false
              },
              pngquant: {
                quality: '65-90',
                speed: 4
              },
              gifsicle: {
                interlaced: false
              },
              webp: {
                quality: 75
              }
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({filename: '[name][hash].css', chunkFilename: '[id][hash].css'}),
    new CleanWebpackPlugin(['dist']),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, 'src/index.html'),
      minify: {
        collapseWhitespace: true,
        removeComments: true,
        removeAttributeQuotes: true, // 移除属性的引号
      }
    })
  ],
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        cache: true, parallel: true, sourceMap: true // set to true if you want JS source maps
      }),
      new OptimizeCSSAssetsPlugin({})
    ]
  }
};

你可以通过npx webpack --config webpack.dev.jsnpx webpack --config webpack.prodjs 在构建时执行不同环境下的配置文件。当然,你最好是在package.json文件中添加脚本来便捷执行:

"scripts":{
 "dev":"npx webpack --config webpack.dev.js",
 "prod":"npm webpack --config webpack.prod.js"
}

以后只需执行:npm run devnpm run prod

6️⃣. 相关构件工具: gulp & fis3

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/ImagineCode/article/details/84142538