用Webpack将Express进行打包【第一部分】

我按照文章的指示试试看。

使用Google翻译做了一个中文译文,仅供参考:

创建一个具有开发和生产构建的Node Express-Webpack应用程序并进行翻译。如果有错误,请指正。

如果原文中没有评论,可以使用引用方式进行书写。

我想做的东西

将开发构建和生产构建分开。

開發版本

    • ES6+のトランスパイル。

 

    • lint

 

    • 単体テスト

 

    • カバレッジレポート

 

    • HMR(Hot Module Reloading)

 

    • minifyしない

 

    imageやcssをBase64エンコードせずに保持する。

生产建设

    • minifyする。

 

    • uglify する。

 

    imageとcssはBase64エンコードする。

为了避免不必要的导入,开发和生产分别使用不同的Express服务器文件和Webpack配置文件进行管理。

技術堆栈

    • Express — server

 

    • Webpack 4 — bundling

 

    • Jest — testing

 

    • Babel — ES6+ transpilation

 

    • ESlint — Linting

 

    • Webpack Dev Middleware — Bundle code in memory instead of in a file

 

    • Webpack Hot Middleware — Enables Hot Module Reloading (HMR)

 

    • UglifyJS — uglifies code

 

    mini-css-extract-plugin — minifies CSS

好的,让我们开始吧。

步骤1:快速服务器

我的验证环境

    • macOS Sierra 10.12.6

 

    • Node v10.0.0

 

    • NPM 6.0.0

 

    • Webpack 4

 

    Express 4.16.3

自己的验证环境

    • Windows8.1

 

    • Node v10.14.1

 

    • NPM 6.4.1

 

    • Webpack 4

 

    Express 4.16.4

建立验证环境目录

mkdir express-webpack
cd express-webpack

创建 package.json 文件

npm init -y

安装Express

npm install --save express

请在 package.json 文件中添加以下内容。

"scripts": {
  "start": "node ./server.js"
},

让我们将基本的Express服务器文件写入项目的根目录server.js,并测试其是否正常工作。

const path = require('path')
const express = require('express')
const app = express(),
            DIST_DIR = __dirname,
            HTML_FILE = path.join(DIST_DIR, 'index.html')
app.use(express.static(DIST_DIR))
app.get('*', (req, res) => {
    res.sendFile(HTML_FILE)
})
const PORT = process.env.PORT || 8080
app.listen(PORT, () => {
    console.log(`App listening to ${PORT}....`)
    console.log('Press Ctrl+C to quit.')
})

当然,创建一个简单美观的 HTML 文件,命名为 “Hello”(index.html)。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Express and Webpack App</title>
    <link rel="shortcut icon" href="#">
</head>
<body>
    <h1>Expack</h1>
    <p class="description">Express and Webpack Boilerplate App</p>
</body>
</html>

现在,为了测试它的运行,执行 npm start 并导航到 http://localhost:8080。页面应该正确显示 HTML。

hello world.jpg

步骤2:安装并启用Webpack

安装与webpack相关的软件包。

webpack — version 4

webpack-cli — cliツール

webpack-node-externals — node-modules をサーバーサイドでbundleする。


npm install --save-dev webpack webpack-cli webpack-node-externals

为了将ES6+转译为ES5,需要安装Babel。

npm install --save-dev babel-core babel-loader babel-preset-env

要将index.html文件复制到dist目录中,需要安装html-loader和html-webpack-plugin。

npm install  --save-dev html-loader html-webpack-plugin

需要创建一个Webpack配置文件 — webpack.config.js。

const path = require('path')
const webpack = require('webpack')
const nodeExternals = require('webpack-node-externals')
const HtmlWebPackPlugin = require("html-webpack-plugin")
module.exports = {
  entry: {
    server: './server.js',
  },
  output: {
    path: path.join(__dirname, 'dist'),
    publicPath: '/',
    filename: '[name].js'
  },
  target: 'node',
  node: {
    // Need this when working with express, otherwise the build fails
    __dirname: false,   // if you don't put this is, __dirname
    __filename: false,  // and __filename return blank or /
  },
  externals: [nodeExternals()], // Need this to avoid error when working with Express
  module: {
    rules: [
      {
        // Transpiles ES6-8 into ES5
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        // Loads the javacript into html template provided.
        // Entry point is set below in HtmlWebPackPlugin in Plugins 
        test: /\.html$/,
        use: [{loader: "html-loader"}]
      }
    ]
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: "./index.html",
      filename: "./index.html",
      excludeChunks: [ 'server' ]
    })
  ]
}

注意:
excludeChunks用于排除名为服务器的文件。这是一个Web文件,对于应用程序本身来说是不必要的,因此不希望将其包含在HTML文件中。

需要在server.js中设置ES6+的import语法来替代require,并测试Babel传输是否正常进行。

import path from 'path'
import express from 'express'
const app = express(),
            DIST_DIR = __dirname,
            HTML_FILE = path.join(DIST_DIR, 'index.html')
app.use(express.static(DIST_DIR))
app.get('*', (req, res) => {
    res.sendFile(HTML_FILE)
})
const PORT = process.env.PORT || 8080
app.listen(PORT, () => {
    console.log(`App listening to ${PORT}....`)
    console.log('Press Ctrl+C to quit.')
})

请在您的根目录下创建一个名为.babelrc的文件,并使用以下代码输入。

{
  'presets': ['env']
}

将package.json文件中的script字段修改为以下内容:

对于Unix系操作系统

"scripts": {
  "build": "rm -rf dist && webpack --mode development",
  "start": "node ./dist/server.js"
},

对于Windows操作系统而言,package.json文件中的代码段如下所示:

“scripts”: {
“build”: “(如果存在 dist 文件夹则删除 dist /s /q) && webpack –mode development”,
“start”: “node ./dist/server.js”
}

Note: This is a translation to simplified Chinese.

通过这种方式,始终从新的 dist 文件夹开始,并通过命令行以声明性的方式设置开发模式。

你可以执行”npm run build”和”npm start”,然后导航到http://localhost:8080进行测试。
在这个阶段,应该没有错误。我正在逐步构建这个步骤,因为我正在写这篇文章。

hello world.jpg

步骤三:为应用程序添加CSS和Javascript的功能

尽管已经实现了相当多的功能,但您可以向应用程序中添加CSS样式、JavaScript和图片。

为了执行这个操作,需要将Webpack配置拆分成两个文件。之后会变为三个文件。

webpack.server.config.jsサーバーコードだけをバンドルする。

webpack.config.jsアプリケーションコードをバンドルする。

接下来,我们将把这个主要的设定文件分成开发版和生产版,并将服务器文件分成开发版和生产版。

首先,让我们安装所需的依赖关系。

npm install --save-dev css-loader file-loader style-loader

我们的目录结构如下

.babelrc
.git
.gitignore
README.md
dist
node_modules
package-lock.json
package.json
webpack.config.js
webpack.server.config.js
src
    index.js
    html
        index.html
    css
        style.css
    js
        logger.js ※原文ではindex.jsだが誤り。
    img
        bg.jpg ※原文ではawful-selfie.jpgだが誤り。原文ではbg.jpgを置く手順が抜けている。
    server
        server.js

调整package.json文件中的脚本配置。

如果是Unix系操作系统

"scripts": {
  "build": "rm -rf dist && webpack --mode development --config webpack.server.config.js && webpack --mode development",
  "start": "node ./dist/server.js"
},

Windows操作系统下,

在package.json文件中的scripts字段中,有如下配置:

“build”: “(如果dist文件夹存在,则删除dist文件夹及其目录下的所有文件) && 使用webpack命令以开发模式执行webpack.server.config.js配置文件 && 使用webpack命令以开发模式执行”,
“start”: “运行node ./dist/server.js命令”。

请更新./src/html/index.html文件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Express and Webpack App</title>
    <link rel="shortcut icon" href="#">
</head>
<body>
    <h1>Expack</h1>
    <p class="description">Express and Webpack Boilerplate App</p>
    <div class="awful-selfie"></div>
</body>
</html>

请更新 ./src/css/style.css 文件。

h1, h2, h3, h4, h5, p {
  font-family: helvetica;
  color: #3e3e3e;
}
.description {
  font-size: 14px;
  color: #9e9e9e;
}
.awful-selfie{
  background: url(../img/bg.jpg);
  width: 300px;
  height: 300px;
  background-size: 100% auto;
  background-repeat: no-repeat;
}

更新 ./src/index.js 文件,检查导入和样式功能是否正常,确认基本功能。

import logMessage from './js/logger'
import './css/style.css'
// Log message to console
logMessage('Welcome to Expack!')

当然的啦。/src/js/logger.js

const logMessage = msg => console.log(msg)
export default logMessage

只需将server.js从根目录移动到./src/server。这将使根目录保持清洁,并将服务器代码保存在适当的位置。

最后,让我们配置Webpack。我们将从./webpack.server.config.js开始。

const path = require('path')
const webpack = require('webpack')
const nodeExternals = require('webpack-node-externals')
module.exports = {
  entry: {
    server: './src/server/server.js',
  },
  output: {
    path: path.join(__dirname, 'dist'),
    publicPath: '/',
    filename: '[name].js'
  },
  target: 'node',
  node: {
    // Need this when working with express, otherwise the build fails
    __dirname: false,   // if you don't put this is, __dirname
    __filename: false,  // and __filename return blank or /
  },
  externals: [nodeExternals()], // Need this to avoid error when working with Express
  module: {
    rules: [
      {
        // Transpiles ES6-8 into ES5
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      }
    ]
  }
}

然后,我们在./webpack.config.js中完成所有的工作。

const path = require("path")
const webpack = require('webpack')
const HtmlWebPackPlugin = require("html-webpack-plugin")
module.exports = {
  entry: {
    main: './src/index.js'
  },
  output: {
    path: path.join(__dirname, 'dist'),
    publicPath: '/',
    filename: '[name].js'
  },
  target: 'web',
  devtool: '#source-map',
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader",
      },
      {
        // Loads the javacript into html template provided.
        // Entry point is set below in HtmlWebPackPlugin in Plugins 
        test: /\.html$/,
        use: [
          {
            loader: "html-loader",
            //options: { minimize: true }
          }
        ]
      },
      {
        test: /\.css$/,
        use: [ 'style-loader', 'css-loader' ]
      },
      {
       test: /\.(png|svg|jpg|gif)$/,
       use: ['file-loader']
      }
    ]
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: "./src/html/index.html",
      filename: "./index.html",
      excludeChunks: [ 'server' ]
    })
  ]
}

请注意使用目标为’web’的app构建方法。这非常重要。请再次确认,如果使用目标为’node’会导致错误。

运行npm run build时,不会发生错误。

expack2.jpg

请点此继续阅读。本篇文章将介绍如何使用Webpack将Express捆绑打包。由于这是一篇在qrunch发表的文章,我稍后会将其上传到Qiita。

广告
将在 10 秒后关闭
bannerAds