从头开始设置Webpack 5





了解如何使用Webpack生成JavaScript,图像,字体和样式,以及如何运行开发服务器。



如果您以前使用过Webpack 4,则与版本5有一些不同:



  • “ webpack-dev-server”命令现在看起来像“ webpack-serve”
  • 不再需要分别安装文件加载器,原始加载器和URL加载器,可以使用内置资产模块
  • 不再支持Node.js的polyfills,因此,例如,如果您在流中遇到错误,则需要在Webpack设置中添加“ stream-browserify”包作为依赖项,并添加{stream:“ stream-browserify”}作为别名


什么是Webpack?



在大多数情况下,网站不再使用纯JavaScript编写而几乎没有JavaScript了-通常,它们仅使用JavaScript构建。因此,有必要构建,最小化和移植代码。这是webpack派上用场的地方。



Webpack是一个模块构建器。它用于打包供浏览器使用的代码。它使您可以利用Babel的最新JavaScript,或使用TypeScript并将其编译为跨浏览器的缩小代码。它还允许您将静态资源导入JavaScript。



对于开发人员,Webpack还提供了一个开发服务器,当保存文件时,该服务器可以即时更新模块和样式。诸如“ vue create”和“ react-create-app”之类的命令行工具在后台使用了webpack,但是您可以轻松地为这些框架创建自己的webpack设置。



Webpack也可以做很多其他事情,但是本文将介绍设置和使用它的基本知识。



安装



创建一个项目目录并对其进行初始化:



mkdir webpack-tutorial
cd !$
// 
cd webpack-tutorial
yarn init -yp  //     "package.json"
// 
npm init -y


安装webpack和webpack-cli作为开发依赖项:



yarn add -D webpack webpack-cli
// 
npm i -D webpack webpack-cli




创建目录“ src”以存储应用程序文件。我将从创建一个简单的“ index.js”文件开始:



console.log(" !")


太好了,我们有一个Node.js项目,其中已安装了主要软件包和一个“ index.js”文件。让我们开始配置webpack。



基本设定



让我们开始配置收集器。在项目的根目录中创建文件“ webpack.config.js”。



入口点


首先,您需要定义应用程序的入口点,即 Webpack将编译哪些文件。在上面的示例中,我们将入口点定义为“ src / index.js”:



// webpack.config.js
const path = require('path')

module.exports = {
    entry: {
        main: path.resolve(__dirname, './src/index.js'),
    },
}


出口点


出口点是Webpack编译的文件所在的目录。将出口点设置为“ dist”。“ [name]”前缀与src中的文件名匹配:



// webpack.config.js
module.exports = {
    // ...

    output: {
        path: path.resolve(__dirname, './dist'),
        filename: '[name].bundle.js',
    },
}


准备用于构建项目的最小设置。将“ build”脚本添加到运行“ webpack”命令的“ package.json”文件中:



// package.json
"scripts": {
    "build": "webpack"
}


启动webpack:



yarn build
// 
npm run build


asset main.bundle.js 19 bytes [emitted] [minimized] (name: main)
./src/index.js 18 bytes [built] [code generated]
webpack 5.1.0 compiled successfully in 152 mss


在“ dist”目录中创建文件“ index.bundle.js”。文件没有更改,但是我们已经成功构建了项目。



外挂程式



插件 界面使webpack非常灵活。Webpack本身和第三方扩展都使用插件。几乎每个项目都使用某些插件。



基于HTML模板的插件


我们有一个现成的程序集,但是没有标记就没有用,它将标记集作为脚本加载。由于我们希望自动生成这样的HTML文件,因此我们使用html-webpack-plugin。





安装插件:



yarn add -D html-webpack-plugin


在“ src”目录中创建一个“ template.html”文件。我们可以向模板添加变量和其他信息。添加变量“ title”,否则模板将看起来像是带有标识符为“ root”的容器的常规HTML文件:



<!-- src/template.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>

  <body>
    <div id="root"></div>
  </body>
</html>


将“ plugins”属性添加到webpack设置中,在其中定义插件,输出文件的名称(index.html)和模板:



// webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    // ...

    plugins: [
        new HtmlWebpackPlugin({
            title: 'webpack Boilerplate',
            template: path.resolve(__dirname, './src/template.html'), // 
            filename: 'index.html', //   
        }),
    ],
}


我们开始组装。现在,“ dist”目录包含“ index.html”文件,其中包含脚本。凉!如果在浏览器中打开此文件,将看到消息“多么有趣!”。在控制台中。



让我们向DOM添加一些内容。让我们更改“ index.js”文件的内容,然后重新启动程序集。



// index.js
//   
const heading = document.createElement('h1')
heading.textContent = ' !'

//    DOM
const root = document.querySelector('#root')
root.append(heading)


转到“ dist”目录并启动服务器(为此,您需要全局安装http-server:yarn global添加http-server或npm i -g http-server)。



http-server


在打开的浏览器标签中,您应该看到标题为“多么有趣!”。还请注意文件大小的减小。



清洁用品


安装clean-webpack-plugin,它在每次构建项目时都会清理“ dist”目录。这使您可以自动删除不再需要的旧文件。





// webpack.config.js
const HtmlWebpackPlugin = require('html=webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
    // ...

    plugins: [
        // ...
        new CleanWebpackPlugin(),
    ],
}


模块和装载机



Webpack使用加载程序来解析模块加载的文件这些可以是JavaScript文件,图像或样式之类的静态资源,以及TypeScript和Babel之类的编译器。Webpack 5有几个内置的资源加载器。



我们的项目有一个HTML文件,该文件加载了一些脚本,但没有执行其他操作。让我们考虑一下我们想要从收藏家那里得到什么?



  • 将最新的JavaScript功能编译为与所有或大多数浏览器兼容的代码
  • 导入样式并将SCSS转换为CSS
  • 导入图像和字体
  • 设置React或Vue(可选)


首先,让我们设置Babel来编译JavaScript。



Babel(JavaScript)


Babel是当今启用未来JavaScript的工具。



我们将定义一个规则,即将使用babel-loader转译项目中的所有js文件(node_modules目录中包含的文件除外)。Babel需要几个依赖项才能工作:





yarn add -D babel-loader @babel/core @babel/preset-env @babel/babel-plugin-proposal-class-properties


// webpack.config.js
module.exports = {
    // ...

    module: {
        rules: [
            // JavaScript
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: ['babel-loader'],
            },
        ],
    }
}


如果要设置TypeScript项目,则对于需要翻译的所有JavaScript文件,都应使用typescript-loader而不是babel-loader。您正在检查带有“ ts”扩展名的文件并使用ts-loader。



这样就建立了Babel,但是该插件还不存在。您可以通过在index.js顶部添加以下代码来验证这一点:



// index.js
//     
class Game {
    name = 'Violin Charades'
}
const myGame = new Game()

//  
const p = document.createElement('p')
p.textContent = `I like ${myGame.game}.`

//   
const heading = document.createElement('h1')
heading.textContent = ' !'

//      DOM
const root = document.querySelector('#root')
root.append(heading, p)


ERROR in ./src/index.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: /Users/you/webpack-tutorial/src/index.js: Support for the experimental syntax 'classProperties' isn't currently enabled (3:8):

  1 | // Create a class property without a constructor
  2 | class Game {
> 3 |   name = 'Violin Charades'
    |        ^
  4 | }


要解决此问题,请在项目的根目录中创建一个“ .babelrc”文件:



// .babelrc
{
  "presets": ["@babel/preset-env"],
  "plugins": ["@babel/plugin-proposal-class-properties"]
}


我们从纱线构建开始构建。现在一切正常。



图片


我们想将图像导入到JavaScript文件中,但是JavaScript无法做到这一点。为了验证这一点,我们创建一个目录“ src / images”,在其中放置一个图像,然后尝试将其导入文件“ index.js”:



// index.js
import example from './images/example.png'

// ...


开始构建时将引发异常:



ERROR in ./src/images/example.png 1:0
Module parse failed: Unexpected character ' ' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders


如前所述,webpack具有一些用于处理静态文件的内置下载器。对于图像,请使用“资产/资源”类型。请注意,我们在谈论的是类型(type),而不是关于加载器(loader):



// webpack.config.js
module.exports = {
    // ...

    module: {
        rules: [
            // 
            {
                test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
                type: 'asset/resource',
            },
        ],
    },
}


新文件出现在“ dist”目录中。



字体和其他嵌入式数据


该webpack还具有一个内置模块来处理一些嵌入式数据,例如字体和SVG。为此,只需指定类型“资产/内联”即可:



// index.js
import example from './images/example.svg'

// ...


// webpack.config.js
module.exports = {
    // ...

    module: {
        rules: [
            //   SVG
            {
                test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
                type: 'asset/inline',
            },
        ],
    },
}


款式


使用样式加载器是在脚本中使用“ import'file.css”之类的字符串的先决条件。



许多人使用CSS-in-JS样式化的组件以及其他允许JavaScript样式化的工具。



有时我们可以限制自己加载一个CSS文件。但是也许您想使用PostCSS,它可以在浏览器中提供最新的CSS功能。还是要使用Sass预处理程序



我想使用所有这三个-用Sass编写代码,用PostCSS处理它,然后编译成CSS。





yarn add -D sass-loader postcss-loader css-loader style-loader postcss-preset-env node-sass


与Babel一样,PostCSS需要一个单独的配置文件:



// postcss.config.js
module.exports = {
    plugins: {
        'post-css-preset-env': {
            browsers: 'last 2 versions',
        },
    },
}


为了测试命名工具的功能,让我们创建一个文件“ src / styles / main.scss”,其中包含Sass变量以及使用PostCSS(lch)的示例:



// src/styles/main.css
$font-size: 1rem;
$font-color: lch(53 105 40);

html {
    font-size: $font-size;
    color: $font-color;
}


我们将此文件导入index.js并添加4个加载程序。webpack从右到左使用加载器,因此最后一个应该是sass-loader,然后是PostCSS,然后是CSS,最后是style-loader,后者将已编译的样式应用于DOM元素:



// index.js
import './styles/main.css'

// ...


// webpack.config.js
module.exports = {
    // ...

    module: {
        rules: [
            // CSS, PostCSS, Sass
            {
                test: /\.(scss|css)$/,
                use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
            },
        ],
    },
}


构建完成后,您会注意到Sass和PostCSS已应用于DOM。



请注意,我们已经设置了开发模式的首选项。对于生产,请使用MiniCssExtractPlugin而不是style-loader,后者会导出缩小的CSS。



发展



每次重新构建项目时,键入纱线构建(npm run build)可能是乏味的。项目越大,构建所需的时间就越长。因此,您需要具有两个webpack配置文件:



  • 生产设置,包括最小化,优化和删除所有资源图(源图)
  • 开发设置包括服务器启动,每次更改更新和资源映射


开发模式可以期望将所需的信息存储在内存中,而不是创建“ dist”目录。



为此,您需要安装webpack-dev-server。





yarn add -D webpack-dev-server


为了演示如何使用服务器进行开发,我们可以在“ webpack.config.js”文件中定义适当的设置。实际上,最好有两个配置文件,一个配置文件为生产模式,另一个配置文件为开发模式。在为您专门准备的webpack 5样板中,我使用webpack-merge在单个文件中获取基本设置,并且特殊要求包含在“ webpack.prod.js”和“ webpack.dev.js”文件中。



// webpack.config.js
const webpack = require('webpack')

module.exports = {
    // ...
    mode: 'development',
    devServer: {
        historyApiFallback: true,
        contentBase: path.resolve(__dirname, './dist'),
        open: true,
        compress: true,
        hot: true,
        port: 8080,
    },
    plugins: [
        // ...
        //      
        new webpack.HotModuleReplacement(),
    ],
}


我们添加了模式:开发和“ devServer”属性。此属性包含几个标准设置-端口号(8080),自动打开浏览器,使用hot-module-replacement,这需要webpack.HotModuleReplacement()。这将允许模块更新而无需重新加载整个页面,即 如果个别样式发生更改,则仅对其进行更新,您无需重新加载JavaScript,从而大大加快了开发速度。



要启动服务器,请使用“ webpack serve”命令:



// package.json
"scripts": {
    "start": "webpack serve"
}


yarn start


运行此命令后,浏览器将在本地主机上打开:8080。现在,您可以修改Sass和JavaScript,它们将即时更新。



结论



我希望本文能帮助您开始使用webpack。为了更轻松地解决您的日常任务,我开发了一个Webpack 5样板,其中包含Babel,Sass,PostCss,用于生产的优化和用于开发的服务器。以它为基础,您可以轻松地将Webpack配置为与React,Vue或TypeScript一起使用。



All Articles