关于前端:从零开始搭建基于webpack4的前端工程化环境

8次阅读

共计 14922 个字符,预计需要花费 38 分钟才能阅读完成。

简介

webpack 是什么?

实质上,webpack 是一个古代 JavaScript 应用程序的动态模块打包器(static module bundler)。在 webpack 解决应用程序时,它会在外部创立一个依赖图(dependency graph),用于映射到我的项目须要的每个模块,而后将所有这些依赖生成到一个或多个 bundle。—— 来自 webpack 官网文档

简略的说,webpack 就是一个古代前端开发的打包机。古代前端十分风行应用模块化的形式开发,webpack 所做的就是将各个 js 模块正当的打包成 bundle 或者 chunk。在打包的过程中,能够通过 loader 的形式,将新的 js 语法、CSS 预处理语言等转换成更容易被浏览器反对的模式。

webpack 是基于 nodejs 的,在绝大部分时,在应用时须要为它写一个配置文件。这个配置文件的次要构造如下:

module.exports = {
    mode: 'development'      // 模式配置
    entry: '',               // 入口文件
    output: {},              // 进口文件
    module: {},              // 解决对应模块
    plugins: [],             // 对应的插件
    devServer: {},           // 开发服务器配置(仅在开发中应用)}

接下来,咱们就来一步步的实现这些配置。

筹备

初始化和装置

在指定文件夹下执行 npm init 进行初始化。

mkdir webpackDemo&&npm init

因为我的项目并不是一个要公布到 npm 的我的项目,所以执行 npm init 后只用一路回车即可。

装置 webpack 和 react 的依赖:

npm install --save-dev webpack react react-dom

在 webpack4 之后的版本中,还须要装置 webpack-cli,具体方法同上。

创立初始目录构造和文件

在我的项目根目录创立 config 文件夹,并在内创立 webpack.config.js。

关上根目录下的 package.json 配置scripts:

"scripts": {"build": "webpack --mode production --config ./config/webpack.config.js",}

配置 scripts 脚本是为了前期在执行过程中只用在命令行中输出 npm ‘ 脚本中指定配置 ’ 就可能实现命令行的输出操作。比方输出 npm build,就会主动执行 “webpack –mode production –config ./config/webpack.config.js” 这一长串的操作。

创立代码文件夹和 react 的入口文件:

在我的项目根目录中创立 src 文件夹,并在内创立 index.js、App.js、index.css。

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css'


ReactDOM.render(
  <App />,
  document.getElementById('root')
);

App.js

import React from 'react';

export default class App extends React.Component {render() {
        return <div>
            <p className="text"> 入手搭建一个基于 webpack4 的 react 开发环境 </p>
        </div>
    }
}

index.css

.text{color:'red'}

实现上述操作后,我的项目目录构造应该像上面这样

webpackDemo
│   node_modules
└───config
    │   webpack.config.js
└───src
    │   index.js
    │   index.css
    │   App.js
    package.json

当初,咱们实现了简略的初始化工作,上面开始理解 webpack 吧。

模式 (mode)

mode 是 webpack4 中新增的概念,它有三个选项:developmentproductionnone,用来设置 webpack 的优化形式。

development

开发模式,该模式优化了开发速度,提供了具体的谬误机制和浏览器调试工具。并且敞开了代码压缩,使代码可能更快的构建。

production

生产模式,该模式可能提供更小的代码包, 去除了只在开发阶段运行的代码。主动开启了代码混同压缩。

配置

module.export = {mode:'production' // 'development'||'production'||'none'}

程序入口 (entry)

在这里,能够申明一个利用的终点。入口能够有一个或者多个。在单页利用中,入口个别只有一个。不过也能够将公共依赖配置成为单页利用的入口,这样单页利用也能够有多个入口。而在多页利用中,个别会有多个入口文件。

一个简略的单页利用入口如下:


module.export = {
  mode:'production' // 'development'||'production'||'none',
  entry:'./src/index.js',
}

输入 (output)

output 用来配置我的项目打包后的文件名称、门路。用来通知 webpack 怎么输入、输入到哪、叫什么名字。

const path = require('path');

module.export = {
  mode:'production' // 'development'||'production'||'none',
  entry:'./src/index.js',
  output: {
    // 在 bundle 中引入正文 留神:该选项不应该在生产模式中启用
    pathinfo:true,
    // 所有输入文件的指标门路
    // 必须是绝对路径(应用 Node.js 的 path 模块)path: path.resolve(__dirname, './../build'),
    // 输入的文件名配置
    filename: "[name].[hash].js"
    }
}

这里的 filename 并没有给它一个理论的名称,而是应用模板字符串去设置 webpack 生成后的文件名称。这个设置中的 [name] 代表模块名称,在单入口文件中默认为 main。而 [hash] 则会生成一个模块标识符的 hash, 默认是 20 位,能够通过 [hash:16] 的形式指定它的位数。打包后的文件名称就像这样main.f236aaeca342dfb1f8dd.js。在生成文件名称后跟上 hash 有助于咱们在我的项目重新部署后因为援用的文件名称变了,浏览器会去下载新的文件,不再持续应用本地的缓存。

loader

webpack 的作用就是将前端开发中的各个模块进行解决以及打包。而 loader 的作用就是解决 webpack 中的这些模块。

webpack 中模块有很多种,常见的有:

  • 模块化的 js 文件
  • css/less/sass 文件
  • 图片以及动态文件

loader 在 module 中配置:

// 示例
const path = require('path');

const appSrc = path.resolve(__dirname, '../src')

module.exports =  {
    mode: 'development',
    // 入口
    entry: './src/index.js',
    // 进口
    output: {
        pathinfo: true,
        // 所有输入文件的指标门路
        // 必须是绝对路径(应用 Node.js 的 path 模块)path: path.resolve(__dirname, './../build'),
        // 输入的文件名配置
        filename: "bundle.js"
    },

    module: {
        rules: [
            {test: /\.(js|jsx)$/,     // 用来指定针对的文件类型 反对正则
                exclude: /node_modules/, // 用来指定须要排除的文件夹,优化打包速度
                include: appSrc,         // 指定所蕴含的文件夹,优化打包速度
                loader: "babel-loader", // 针对指定文件应用的 loader
            }
        ]
    }
};

要对这些模块进行解决,就要应用到不同的 loader。在此之前,先简略的介绍一下须要应用到的 loader。

babel-loader

babel 是一个语法转换器,可能让你自在的应用 JavaScript 的最新语法。它可能将咱们所写的新语法、jsx 等转换成浏览器可能敌对反对的模式。

要应用 babel-loader 须要下列依赖, 能够通过执行 npm install --save-dev babel-loader @babel/core @babel/preset-react @babel/preset-env 装置它们。

  • babel-loader
  • @babel/core
    babel 的外围组件, 外面蕴含着 babel 的 api。
  • @babel/preset-env
    用来本义 JavaScript 语法。
  • @babel/preset-react
    用来本义 react。

配置 babel-loader:

const path = require('path');

const appSrc = path.resolve(__dirname, '../src')

module.exports =  {
    mode: 'development',
    // 入口
    entry: './src/index.js',
    // 进口
    output: {
        pathinfo: true,
        // 所有输入文件的指标门路
        // 必须是绝对路径(应用 Node.js 的 path 模块)path: path.resolve(__dirname, './../build'),
        // 输入的文件名配置
        filename: "bundle.js"
    },
    module: {
        rules: [
            {test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                include: appSrc,
                loader: "babel-loader",
                options: {
                    // 指定 babel 预处理本义
                    presets: ["@babel/preset-env", "@babel/preset-react"]
                }
            }
        ]
    }
}

实现上述配置后,还需配置一下 babel,让它可能转换 react 和 js 的新语法。能够像下面应用 webpack 配置中的 option 选项中的 presets 字段指定 babel 预处理的形式。

也能够在我的项目的根目录创立 babel 的配置文件 .babelrc.babelrc 后缀 rc 来自 linux 中,应用过 linux 就晓得 linux 中很多 rc 结尾的文件,比方.bashrc,rc 是 run command 的缩写,翻译成中文就是运行时的命令,示意程序执行时就会来调用这个文件。

babel 所有的操作根本都会来读取这个配置文件,除了一些在回调函数中设置 options 参数的,如果没有这个配置文件,会从 package.json 文件的 babel 属性中读取配置。

.babelrc 中增加下列语句:

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

url-loader

url-loader 和 file-loader 的作用相似,都是使 webpack 可能打包动态文件。url-loader 相较于 file-loader 的性能更弱小,它可能应用两种形式进行打包。

url-loader 有一个重要的参数 limit , 这个参数用来设置打包文件大小的限度。当文件小于指定参数时,它可能返回一个 DataURL(base64)局势的文件。当文件大于指定参数时,它将通过 file-loader 进行打包。

配置 url-loader:

const path = require('path');

const appSrc = path.resolve(__dirname, '../src')

module.exports =  {
    mode: 'development',
    // 入口
    entry: './src/index.js',
    // 进口
    output: {
        pathinfo: true,
        // 所有输入文件的指标门路
        // 必须是绝对路径(应用 Node.js 的 path 模块)path: path.resolve(__dirname, './../build'),
        // 输入的文件名配置
        filename: "bundle.js"
    },
    module: {
        rules: [
            {test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                include: appSrc,
                loader: "babel-loader",options: {
                    // 指定 babel 预处理本义
                    presets: ["@babel/preset-env", "@babel/preset-react"]
                }
            },
            // url-loader 的配置
            {test: /\.(png|jpg|gif)$/,
                loader: "url-loader",
                options: {
                    // 设置 url-loader 转 DataURL 的文件大小下限
                    limit: 10000
                }
            }
        ]
    }
}

url-loader 还有两个参数 mimetypefallback,这两个参数应用的并不多,就不在这里赘述了。

style-loader 和 css-loader

style-loader 和 css-loader 都是用来解决 css 文件的,不过它们的作用并不相同。

css-loader:用来读取 css 文件的内容,并进行解决 如:minimize。

style-loader:将通过 import 模式导入到 js 中的 css 文件插入到 <style></style> 标签内。

在 webpack 中的配置如下:

const path = require('path');

const appSrc = path.resolve(__dirname, '../src')

module.exports =  {
    mode: 'development',
    // 入口
    entry: './src/index.js',
    // 进口
    output: {
        pathinfo: true,
        // 所有输入文件的指标门路
        // 必须是绝对路径(应用 Node.js 的 path 模块)path: path.resolve(__dirname, './../build'),
        // 输入的文件名配置
        filename: "bundle.js"
    },
    module: {
        rules: [
            {test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                include: appSrc,
                loader: "babel-loader",options: {
                    // 指定 babel 预处理本义
                    presets: ["@babel/preset-env", "@babel/preset-react"]
                }
            },
            {test: /\.(png|jpg|gif)$/,
                loader: "url-loader",
                options: {
                    // 设置 url-loader 转 DataURL 的文件大小下限
                    limit: 10000
                }
            },
            // 针对 css 文件配置 style-loader 和 css-loader
            {
                test: /\.css$/,
                include: appSrc,
                use: [
                        'style-loader',
                    {
                        loader: 'css-loader',
                        options: {
                            // 能够蕴含一些配置
                            modules:true|false, // 是否开启 css 模块化,开启后引入的 css 文件仅针对以后页面无效,不会作用到全局
                            minimize: true // 开发模式下应该设为 false,优化打包速度
                        }
                    }
                ]
            }
        ]
    }
}

如上所示,当咱们在针对同一类型的文件配置多个 loader 时。能够将 loader 申明在一个数组内,数组项能够是一个对象,也能够仅仅是一个字符串,这取决于你针对某个 loader 还有没有非凡的设置。比方在配置 css-loader 时,还申明了 option 选项,并在 option 选项内开启了 minimize 选项。然而在配置 style-loader 时,仅仅写了一个字符串。

须要留神的是,数组内 loader 的执行程序是从数组的最初一项顺次向前执行。所有咱们将 css-loader 配置在了前面,它是先执行的。这更合乎解决逻辑,先对 css 进行解决,再插入到 html 中。

插件

插件是 webpack 的一个极其重要的性能,webpack 提供了丰盛的插件接口,使开发者可能自在的开发插件来拓展 webpack 的性能。

这里咱们拿赫赫有名的 HtmlWebpackPlugin 来举例。

构想一个场景,在打包时,须要手动的去创立一个 html 文件,而后在其中引入打包好的各种文件。即便创立好 html 文件后,因为在 config 中设置了 hash 模式的打包文件名称。咱们在每次打包后还须要依据 hash 名称的变动去扭转 html 内引入的文件名称,这是十分低级的反复劳作。

HtmlWebpackPlugin 为咱们解决了这个问题。HtmlWebpackPlugin 可能依据咱们提供的模板主动生成 html 文件,并引入打包后的内容。

上面介绍一下 HtmlWebpackPlugin 的应用过程。

装置:npm install --save-dev html-webpack-plugin

装置实现后,先在我的项目的根目录创立一个文件夹public,在其中创立一个模板文件index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>

而后在 webpack 中配置插件:

const path = require('path');

const appSrc = path.resolve(__dirname, '../src')
// 引入 html-webpack-plugin 插件
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports =  {
    mode: 'development',
    // 入口
    entry: './src/index.js',
    // 进口
    output: {
        pathinfo: true,
        // 所有输入文件的指标门路
        // 必须是绝对路径(应用 Node.js 的 path 模块)path: path.resolve(__dirname, './../build'),
        // 输入的文件名配置
        filename: "bundle.js"
    },
    module: {
        rules: [
            {test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                include: appSrc,
                loader: "babel-loader",
                options: {
                    // 指定 babel 预处理本义
                    presets: ["@babel/preset-env", "@babel/preset-react"]
                }
            },
            {test: /\.(png|jpg|gif)$/,
                loader: "url-loader",
                options: {
                    // 设置 url-loader 转 DataURL 的文件大小下限
                    limit: 10000
                }
            },
            // 针对 css 文件配置 style-loader 和 css-loader
            {
                test: /\.css$/,
                include: appSrc,
                use: [
                        'style-loader',
                    {
                        loader: 'css-loader',
                        options: {
                            // 能够蕴含一些配置

                            minimize: true // 开发模式下应该设为 false,优化打包速度
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        // HTML 模板文件解决插件
        new HtmlWebpackPlugin({
            file: 'index.html', // 生成的文件名称
            template: 'public/index.html' // 指定模板文件
        })
    ],
}

当初在命令行中执行npm build,webpack 将打包 src 目录内的文件。并将在根目录生成一个 build 文件,将打包的内容输入在外面。

这时候,咱们其实曾经实现了 webpack 的根本配置。然而当初的配置是基于 development 模式进行打包的,没有进行压缩,很显然这并不能做为一个可公布的版本。要批改为生产模式其实也很简略,能够通过两种形式去实现。

  1. 批改配置文件中的 mode 选项,将 development 批改为 production。
  2. 删除配置中的 mode 选项,批改 package.json scripts 中的 build 项为 webpack --mode production --config ./config/webpack.config.js

在配置 2 中,应用 –mode 可能为 webpack-cli 设置打包模式。批改后再次打包,这时候代码通过 webpack production 模式的优化,进行了混同压缩,变成了公布版本。

devServer

在日常的开发过程中,必定不能每批改一点货色就从新 build 一次,这样开发效率会受到很大的影响。这时须要启动一个服务,来监听文件的变动。当文件保留时就从新打包,同时帮咱们主动刷新浏览器,不便咱们及时察看到更新。

要实现上述操作有几种形式,这里只介绍其中的一种,应用 webpack-dev-server 插件。

执行 npm install --save-dev webpack-dev-server 装置插件,在 module.explot 中增加配置项 devServer

devServer 的配置项有很多,这里大略的介绍其中几种罕用的配置:

  • contentBase: ”, 通知服务器从哪个目录中提供内容
  • https: true|false, 是否启用 https
  • compress: true|false, 是否启用压缩
  • host: ‘127.0.0.1’,  指定 host 地址
  • port: 23333, 指定端口
  • overlay: true|false, 当呈现编译器谬误或正告时,在浏览器中显示全屏覆盖层。
  • progress: true|false, 将运行进度输入到控制台。

将 devServer 增加到配置中:

const path = require('path');

const appSrc = path.resolve(__dirname, '../src')
// 引入 html-webpack-plugin 插件
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports =  {
    // 入口
    entry: './src/index.js',
    // 进口
    output: {
        pathinfo: true,
        // 所有输入文件的指标门路
        // 必须是绝对路径(应用 Node.js 的 path 模块)path: path.resolve(__dirname, './../build'),
        // 输入的文件名配置
        filename: "bundle.js"
    },
    module: {
        rules: [
            {test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                include: appSrc,
                loader: "babel-loader",
                options: {
                    // 指定 babel 预处理本义
                    presets: ["@babel/preset-env", "@babel/preset-react"]
                }
            },
            {test: /\.(png|jpg|gif)$/,
                loader: "url-loader",
                options: {
                    // 设置 url-loader 转 DataURL 的文件大小下限
                    limit: 10000
                }
            },
            // 针对 css 文件配置 style-loader 和 css-loader
            {
                test: /\.css$/,
                include: appSrc,
                use: [
                        'style-loader',
                    {
                        loader: 'css-loader',
                        options: {
                            // 能够蕴含一些配置

                            minimize: true // 开发模式下应该设为 false,优化打包速度
                        }
                    }
                ]
            }
        ]
    },
    devServer: {
        // HOST
        host: '127.0.0.1',
        // 端口
        port: 23333,
        // 报错提醒在网页遮罩层
        overlay: true,
        // 显示运行进度
        progress: true,
    },
    plugins: [
        // HTML 模板文件解决插件
        new HtmlWebpackPlugin({
            file: 'index.html', // 生成的文件名称
            template: 'public/index.html' // 指定模板文件
        })
    ]
}

须要留神的时,devServer 该当用在开发环境中,所以当初须要将之前的配置进行批改。

  1. 在配置中删除 mode 项。
  2. 为 package.json 的 scripts 中增加另一个启动命令 "start": "webpack-dev-server --open --mode development --config ./config/webpack.config.js"
  3. 将之前的 build 项改为 webpack --mode production --config ./config/webpack.config.js

当初,执行 npm build,webpack 将应用 production 模式进行打包。执行 npm start 时,将应用 development 模式进行打包,并且 webpack-dev-server 将启动一个服务,监听文件变更。

当初执行 npm start,就能够开始进行开发了!

进阶

在下面的配置中,咱们曾经实现了一个 react 我的项目开发环境的根本配置。但这远远不够,在理论的我的项目中,可能会用到很多的工具来优化开发速度。同时也须要针对不同的环境写不同的配置,做不同的优化等。并且,可能还波及到代码宰割、压缩等配置。

上面,咱们来一步步欠缺 webpack 的配置。

devtool

webpack 中 devtool 选项用来管制是否生成,以及如何生成 source map。

想要理解 source map,能够看一下这篇文章。简略的说,source map 就是帮忙咱们定位到错误信息地位的文件。正确的配置 source map,可能进步开发效率,更快的定位到谬误地位。

webpack 中 devtool 有很多种配置,咱们能够在 这里 理解它。

在开发环境中,更举荐应用cheap-module-eval-source-map, 它能帮忙咱们精确的定位到谬误源代码地位的同时,也能提供更快的构建速度和构建性能。

而在生产环境中,能够不启动任何 source map(不配置 devtool 项),也能够应用source-map。须要留神的是,不要将 source map 部署到生产服务器中。

为 svg 文件配置 loader

个别状况下,我的项目都会须要用到图标。常见的图标应用形式有很多种,如雪碧图、字体图标、svg 等。雪碧图和 iconfont 的应用形式不须要进行非凡的解决,这里咱们就不再赘述。上面介绍一个应用 svg 图标的办法。

通过 svgr , 可能间接将 svg 图标以 react 组件的模式引入我的项目中。

就像这样:

import React from 'react';
import {ReactComponent as Icon} from './icon.svg';

export default class App extends React.Component {render() {
        return <div>
            <Icon width={10} height={10} />
        </div>
    }
}

在 react 最新版本的 cli create-react-app, 已近默认集成了 svgr。在咱们本人的我的项目中应用也很简略,只须要针对 .svg增加 loader 即可。

{
  test: /\.svg$/,
  use: ['@svgr/webpack'],
}

svgr 同时也反对 node、react-native 等解决形式,能够通过 svgr 文档来理解。

构建不同环境下的配置

在生产环境和开发环境的构建指标差别很大。比方在开发环境中,须要更快的构建速度和更强的谬误提醒。然而在生产环境中,则心愿构建的代码能更小,更轻,更侧重于性能。所以,针对不同的环境,须要不同的配置文件。然而如果将配置齐全拆离开,两个配置文件中可能会蕴含很多反复的代码。这时咱们须要提出公共的配置,为了将这些配置合并在一起,能够应用 webpack-merge。

上面,咱们开始应用 webpack-merge 进行配置优化。

首先,应用 npm 装置依赖 npm install --save-dev webpack-merge

而后,在 config 文件夹下创立 webpack.config.common.js、webpack.config.dev.js、webpack.config.prod.js。顾名思义,这三个配置代表了通用、开发、生产模式的配置文件。

将之前配置中用到的公共配置提出到 webpack.config.common.js 内:

// webpack.config.common.js

// 打包 HTML 文件
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const appSrc = path.resolve(__dirname, '../src')

module.exports = {
    // 入口
    entry: './src/index.js',
    module: {
        rules: [
            {
                // 配置 svg 图标 loader,能够在我的项目中通过组件的模式间接引入 svg 图标
                test: /\.svg$/,
                include: appSrc,
                use: ['@svgr/webpack']
            }
        ]
    },
    plugins: [
        // HTML 模板文件解决插件
        new HtmlWebpackPlugin({
            file: 'index.html',
            template: 'public/index.html'
        })
    ]
}

开发环境下的配置:

const merge = require('webpack-merge');
// 引入公共配置文件
const common = require('./webpack.config.common.js');
const path = require('path');

const appSrc = path.resolve(__dirname, '../src')

module.exports = merge(common, {
    mode: 'development',
    devtool: 'cheap-module-eval-source-map',
    // 进口
    output: {
        pathinfo: true,
        // 所有输入文件的指标门路
        // 必须是绝对路径(应用 Node.js 的 path 模块)// chunk 名称配置
        chunkFilename: '[name].chunk.js',
        // 输入的文件名配置
        filename: "bundle.js"
    },
    module: {
        rules: [
            {test: /\.(js|jsx)$/,
                // exclude: /node_modules/,
                include: appSrc,
                loader: "babel-loader",
                options: {presets: ["@babel/preset-env", "@babel/preset-react"]
                }
            },
            // 针对动态文件
            {test: /\.(png|jpg|gif)$/,
                loader: "url-loader",
                options: {
                    limit: 8192,
                    name: 'static/[name].[hash:8].[ext]',
                }
            },
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader',
                        options: {minimize: false}
                    }
                ]
            }
        ]
    },
    devServer: {
        // HOST
        host: '127.0.0.1',
        // 端口
        port: 23333,
        // 报错提醒在网页遮罩层
        overlay: true,
        // 显示运行进度
        progress: true,
    }
})

生产环境配置文件:

const path = require('path');
const merge = require('webpack-merge');
const common = require('./webpack.config.common.js');
// 每次执行打包 先革除之前的打包文件
const CleanWebpackPlugin = require('clean-webpack-plugin');

const appSrc = path.resolve(__dirname,'../src')

module.exports = merge(common, {
    mode: 'production',
    // 进口
    output: {
        pathinfo: false,
        chunkFilename: 'js/[name].chunk.js',
        // 所有输入文件的指标门路
        // 必须是绝对路径(应用 Node.js 的 path 模块)path: path.resolve(__dirname, './../build'),
        filename: "js/[name].[chunkhash:8].js"
    },
    module: {
        rules: [
            {test: /\.(js|jsx)$/,
                include: appSrc,
                // exclude: /node_modules/,
                loader: "babel-loader",
                options: {presets: ["@babel/preset-env", "@babel/preset-react"]
                }
            },
            // 针对动态文件
            {test: /\.(png|jpg|gif)$/,
                loader: "url-loader",
                options: {
                    limit: 10000,
                    name: 'static/[name].[hash:8].[ext]',
                }
            },
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader',
                        options: {minimize: true}
                    }
                ]
            }

        ]
    },
    plugins: [
        // 打包前革除之前的 build 目录
        new CleanWebpackPlugin(['build'], path.resolve(__dirname, '../'))
    ]
});

当初配置曾经批改实现,咱们还须要批改一下 package.json,让启动命令去援用不同的配置文件。

将开发模式的启动配置批改为 "start": "webpack-dev-server --open --mode development --config ./config/webpack.config.dev.js"

生产模式的启动配置批改为 "build": "webpack --mode production --config ./config/webpack.config.prod.js",

当初咱们应用 npm start 命令启动我的项目,运行的是 webpack.config.dev.js 文件,这是开发配置文件,咱们能够在外面做一些针对开发模式的优化。

应用 npm build 命令启动我的项目,运行的是 webpack.config.prod.js 文件,这是生产配置文件,咱们能够在外面做一些针对生产模式的优化。

避免打包文件的反复

执行 build 命令打包文件时,会在我的项目的根目录下生成 build 目录,并在其中生成打包文件。当执行屡次 build 后,会发现因为项目名称的 hash 值不同,build 目录下可能存在多个版本打包后的文件。要解决这个问题,能够应用插件 clean-webpack-plugin

首先装置插件 npm i clean-webpack-plugin --save-dev

配置如下:

const CleanWebpackPlugin = require('clean-webpack-plugin')

// webpack config
{
  plugins: [new CleanWebpackPlugin(['build'], path.resolve(__dirname, '../'))
  ]
}

配置完插件后,再执行 npm build 命令。会发现每次打包前,build 目录都会被删除,而后从新创立。

留神,该插件只用于生产环境配置。

总结

到这里,咱们实现了 webpack 的根底的配置,以及各种概念的扫盲。其实这只能算是根底用法,要实现一个真正欠缺的 webpack 配置必定远远不止这些。

在把握了上述根底配置后,大家能够尝试着进行一些更深刻的学习,如 optimization、tree shaking、生产环境下的构建速度优化等。

正文完
 0