webpack学习配置笔记(一)

学习链接:webpack中文官网

安装webpack

本地安装

npm install --save-dev webpack
npm install --save-dev webpack@<version>

对于大多数项目,我们建议本地安装。这可以使我们在引入破坏式变更(breaking change)的依赖时,更容易分别升级项目。通常,webpack 通过运行一个或多个 npm scripts,会在本地 node_modules 目录中查找安装的 webpack:

"scripts":{
    "start":"webpack --config webpack.config.js"
}

全局安装

npm install --global webpack

最新体验版本

npm install webpack@beta
npm install webpack/webpack

安装这些最新体验版本时要小心!它们可能仍然包含 bug,因此不应该用于生产环境。

起步

创建目录,初始化npm ,和在本地安装webpack

mkdir webpack-demo && cd webpack-demo
npm init -y
npm install --save-dev webpack

Lodash

有多年开发经验的工程师,往往都会有自己的一套工具库,称为 utils、helpers 等等,这套库一方面是自己的技术积累,另一方面也是对某项技术的扩展,领先于技术规范的制定和实现。

Lodash 就是这样的一套工具库,它内部封装了诸多对字符串、数组、对象等常见数据类型的处理函数,其中部分是目前 ECMAScript 尚未制定的规范,但同时被业界所认可的辅助函数。目前每天使用 npm 安装 Lodash 的数量在百万级以上,这在一定程度上证明了其代码的健壮性,值得我们在项目中一试。

Lodash

安装

npm install --save lodash

管理资源

加载css

为了从 JavaScript 模块中 import 一个 CSS 文件,你需要在 module 配置中 安装并添加 style-loader 和 css-loader:

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

修改webpack.config.js

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    module:{
        rules:[
            {
                test:/\.css$/,
                use:[
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    }
};

现在我们可以使用import './style.css'这种代码了。

加载图片

假想,现在我们正在下载 CSS,但是我们的背景和图标这些图片,要如何处理呢?使用 file-loader,我们可以轻松地将这些内容混合到 CSS 中:

npm install --save-dev file-loader

webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        },
+       {
+         test: /\.(png|svg|jpg|gif)$/,
+         use: [
+           'file-loader'
+         ]
+       }
      ]
    }
  };

file-loader
合乎逻辑下一步是,压缩和优化您的图像。查看 image-webpack-loaderurl-loader,以了解更多关于如果增强加载处理图片功能。

加载字体

那么,像字体这样的其他资源如何处理呢?file-loader 和 url-loader 可以接收并加载任何文件,然后将其输出到构建目录。这就是说,我们可以将它们用于任何类型的文件,包括字体。让我们更新 webpack.config.js 来处理字体文件:

 const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        },
        {
          test: /\.(png|svg|jpg|gif)$/,
          use: [
            'file-loader'
          ]
        },
+       {
+         test: /\.(woff|woff2|eot|ttf|otf)$/,
+         use: [
+           'file-loader'
+         ]
+       }
      ]
    }
  };

加载数据

此外,可以加载的有用资源还有数据,如 JSON 文件,CSV、TSV 和 XML。类似于 NodeJS,JSON 支持实际上是内置的,也就是说 import Data from './data.json' 默认将正常运行。要导入 CSV、TSV 和 XML,你可以使用 csv-loaderxml-loader。让我们处理这三类文件:

npm install --save-dev csv-loader xml-loader

webpack.config.js

 const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        },
        {
          test: /\.(png|svg|jpg|gif)$/,
          use: [
            'file-loader'
          ]
        },
        {
          test: /\.(woff|woff2|eot|ttf|otf)$/,
          use: [
            'file-loader'
          ]
        },
+       {
+         test: /\.(csv|tsv)$/,
+         use: [
+           'csv-loader'
+         ]
+       },
+       {
+         test: /\.xml$/,
+         use: [
+           'xml-loader'
+         ]
+       }
      ]
    }
  };

管理输出

webpack.config.js

const path = require('path');

module.exports = {
    // entry: './src/index.js',
    entry:{
        app:'./src/index.js',
        print:'./src/print.js'
    },
    output: {
        // filename: 'bundle.js',
        filename:'[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    }
    ...
};

执行npm run build后,我们可以看到

Hash: 1e971c5b5f7389f57299
Version: webpack 3.9.1
Time: 785ms
          Asset     Size  Chunks                    Chunk Names
  app.bundle.js   561 kB    0, 1  [emitted]  [big]  app
print.bundle.js  2.74 kB       1  [emitted]         print
   [0] ./src/print.js 85 bytes {0} {1} [built]
   [1] ./src/index.js 430 bytes {0} [built]
   [3] (webpack)/buildin/global.js 509 bytes {0} [built]
   [4] (webpack)/buildin/module.js 517 bytes {0} [built]
   [5] ./src/style.css 1.04 kB {0} [built]
   [6] ./node_modules/.0.28.7@css-loader!./src/style.css 198 bytes {0} [built]
    + 4 hidden modules

我们可以看到,webpack 生成 print.bundle.js 和 app.bundle.js 文件,这也和我们在 index.html 文件中指定的文件名称相对应。如果你在浏览器中打开 index.html,就可以看到在点击按钮时会发生什么。

但是,如果我们更改了我们的一个入口起点的名称,甚至添加了一个新的名称,会发生什么?生成的包将被重命名在一个构建中,但是我们的index.html文件仍然会引用旧的名字。我们用 HtmlWebpackPlugin 来解决这个问题。

设定HtmlWebpackPlugin

安装

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

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    // entry: './src/index.js',
    entry:{
        app:'./src/index.js',
        print:'./src/print.js'
    },
    output: {
        // filename: 'bundle.js',
        filename:'[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    module:{
        ...
    },
    plugins:[
        new HtmlWebpackPlugin({
            title:'Output Management'
        })
    ]
};

在我们构建之前,你应该了解,虽然在 dist/ 文件夹我们已经有 index.html 这个文件,然而 HtmlWebpackPlugin 还是会默认生成 index.html 文件。这就是说,它会用新生成的 index.html 文件,把我们的原来的替换。让我们看下在执行 npm run build 后会发生什么:

Hash: f6192796510782b20e6c
Version: webpack 3.9.1
Time: 1028ms
          Asset       Size  Chunks                    Chunk Names
  app.bundle.js     561 kB    0, 1  [emitted]  [big]  app
print.bundle.js    2.74 kB       1  [emitted]         print
     index.html  254 bytes          [emitted]         
   [0] ./src/print.js 85 bytes {0} {1} [built]
   [1] ./src/index.js 430 bytes {0} [built]
   [3] (webpack)/buildin/global.js 509 bytes {0} [built]
   [4] (webpack)/buildin/module.js 517 bytes {0} [built]
   [5] ./src/style.css 1.04 kB {0} [built]
   [6] ./node_modules/.0.28.7@css-loader!./src/style.css 198 bytes {0} [built]
    + 4 hidden modules
Child html-webpack-plugin for "index.html":
     1 asset
       [2] (webpack)/buildin/global.js 509 bytes {0} [built]
       [3] (webpack)/buildin/module.js 517 bytes {0} [built]
        + 2 hidden modules

如果你在代码编辑器中将 index.html 打开,你就会看到 HtmlWebpackPlugin 创建了一个全新的文件,所有的 bundle 会自动添加到 html 中。

如果你想要了解更多 HtmlWebpackPlugin 插件提供的全部功能和选项,那么你就应该多多熟悉 HtmlWebpackPlugin 仓库。

你还可以看一下 html-webpack-template,除了默认模板之外,还提供了一些额外的功能。

清理/dist文件夹

你可能已经注意到,由于过去的指南和代码示例遗留下来,导致我们的 /dist 文件夹相当杂乱。webpack 会生成文件,然后将这些文件放置在 /dist 文件夹中,但是 webpack 无法追踪到哪些文件是实际在项目中用到的。

通常,在每次构建前清理 /dist 文件夹,是比较推荐的做法,因此只会生成用到的文件。让我们完成这个需求。

clean-webpack-plugin 是一个比较普及的管理插件,让我们安装和配置下。

npm isntall clean-webpack-plugin --save-dev
cnpm isntall clean-webpack-plugin --save-dev

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
    // entry: './src/index.js',
    entry:{
        app:'./src/index.js',
        print:'./src/print.js'
    },
    output: {
        // filename: 'bundle.js',
        filename:'[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    module:{
        rules:[
            ...
        ]
    },
    plugins:[
        new CleanWebpackPlugin(['dist']),//清理的文件夹
        new HtmlWebpackPlugin({
            title:'Output Management'
        })
    ]
};

Manifest

你可能会感兴趣,webpack及其插件似乎“知道”应该哪些文件生成。答案是,通过 manifest,webpack 能够对「你的模块映射到输出 bundle 的过程」保持追踪。如果你对通过其他方式来管理 webpack 的输出更感兴趣,那么首先了解 manifest 是个好的开始。

通过使用 WebpackManifestPlugin,可以直接将数据提取到一个 json 文件,以供使用。

我们不会在此展示一个关于如何在你的项目中使用此插件的完整示例,但是你可以仔细深入阅读 manifest 的概念页面,以及通过缓存指南来弄清如何与长期缓存相关联。

开发

在这里我们学习如何搭建一个开发环境,让我们的开发更容易一些。

使用source map

为了更容易地追踪错误和警告,JavaScript 提供了 source map 功能,将编译后的代码映射回原始源代码。如果一个错误来自于 b.js,source map 就会明确的告诉你。
source map 有很多不同的选项可用,请务必仔细阅读它们,以便可以根据需要进行配置。

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
    // entry: './src/index.js',
    entry:{
        app:'./src/index.js',
        print:'./src/print.js'
    },
    output: {
        // filename: 'bundle.js',
        filename:'[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    module:{
        rules:[
            ...
        ]
    },
    plugins:[
        new CleanWebpackPlugin(['dist']),//清理的文件夹
        new HtmlWebpackPlugin({
            title:'Output Management'
        })
    ],
    devtool:'inline-source-map'
};

添加devtool:'inline-source-map'

选择一个开发工具

每次要编译代码时,手动运行 npm run build 就会变得很麻烦。

webpack 中有几个不同的选项,可以帮助你在代码发生变化后自动编译代码:

webpack's Watch Mode
webpack-dev-server
webpack-dev-middleware
多数场景中,你可能需要使用 webpack-dev-server,但是不妨探讨一下以上的所有选项。

使用观察模式

你可以指示 webpack "watch" 依赖图中的所有文件以进行更改。如果其中一个文件被更新,代码将被重新编译,所以你不必手动运行整个构建。

我们添加一个用于启动 webpack 的观察模式的 npm script 脚本:

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "watch": "webpack --watch",
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "clean-webpack-plugin": "^0.1.17",
    "css-loader": "^0.28.7",
    "csv-loader": "^2.1.1",
    "file-loader": "^1.1.5",
    "html-webpack-plugin": "^2.30.1",
    "style-loader": "^0.19.0",
    "webpack": "^3.9.1",
    "xml-loader": "^1.2.1"
  },
  "dependencies": {
    "lodash": "^4.17.4"
  }
}

现在,你可以在命令行中运行 npm run watch,就会看到 webpack 编译代码,然而却不会退出命令行。这是因为 script 脚本还在观察文件。

唯一的缺点是,为了看到修改后的实际效果,你需要刷新浏览器。如果能够自动刷新浏览器就更好了,可以尝试使用 webpack-dev-server,恰好可以实现我们想要的功能。

使用webpack-dev-server

webpack-dev-server 为你提供了一个简单的 web 服务器,并且能够实时重新加载(live reloading)。

npm install --save-dev webpack-dev-server
cnpm install --save-dev webpack-dev-server

修改配置文件,告诉开发服务器(dev server),在哪里查找文件:
webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
    // entry: './src/index.js',
    entry:{
        app:'./src/index.js',
        print:'./src/print.js'
    },
    output: {
        // filename: 'bundle.js',
        filename:'[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    module:{
        rules:[
            ...
        ]
    },
    plugins:[
        new CleanWebpackPlugin(['dist']),//清理的文件夹
        new HtmlWebpackPlugin({
            title:'Output Management'
        })
    ],
    devtool:'inline-source-map',
    devServer:{
        contentBase:'./dist'
    }
};

以上配置告知 webpack-dev-server,在 localhost:8080 下建立服务,将 dist 目录下的文件,作为可访问文件。

让我们添加一个 script 脚本,可以直接运行开发服务器(dev server):
package.json

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "watch": "webpack --watch",
    "start": "webpack-dev-server --open"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "clean-webpack-plugin": "^0.1.17",
    "css-loader": "^0.28.7",
    "csv-loader": "^2.1.1",
    "file-loader": "^1.1.5",
    "html-webpack-plugin": "^2.30.1",
    "style-loader": "^0.19.0",
    "webpack": "^3.9.1",
    "webpack-dev-server": "^2.9.5",
    "xml-loader": "^1.2.1"
  },
  "dependencies": {
    "lodash": "^4.17.4"
  }
}

我这边试了一下后,发现如果webpack-dev-server启动起来的话,还需要安装下面的东西

cnpm install --save-dev parseurl
cnpm install --save-dev express 

然后才能启动起来。
就是执行npm start命令。

使用webpack-dev-middleware

webpack-dev-middleware 是一个中间件容器(wrapper),它将通过 webpack 处理后的文件发布到一个服务器(server)。在内部 webpack-dev-server 它使用,然而,它可以作为一个单独的包来提供,可以进行更多的自定义设置来实现更多需求。接下来是一个 webpack-dev-middleware 配合 express server 的示例。

首先,安装 express 和 webpack-dev-middleware:

npm install --save-dev express webpack-dev-middleware

接下来我们需要对 webpack 的配置文件做一些调整,以确保中间件(middleware)功能能够正确启用:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
    // entry: './src/index.js',
    entry:{
        app:'./src/index.js',
        print:'./src/print.js'
    },
    output: {
        // filename: 'bundle.js',
        filename:'[name].bundle.js',
        path: path.resolve(__dirname, 'dist'),
+        publicPath:'/'
    },
    module:{
        rules:[
           ...
        ]
    },
    plugins:[
        new CleanWebpackPlugin(['dist']),//清理的文件夹
        new HtmlWebpackPlugin({
            title:'Output Management'
        })
    ],
    devtool:'inline-source-map',
    devServer:{
        contentBase:'./dist'
    }
};

publicPath 也会在服务器脚本用到,以确保文件资源能够在 http://localhost:3000 下正确访问,我们稍后再设置端口号。下一步就是设置我们自定义的 express 服务:
project

webpack-demo
  |- package.json
  |- webpack.config.js
+ |- server.js
  |- /dist
  |- /src
    |- index.js
    |- print.js
  |- /node_modules

server.js

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(webpackDevMiddleware(compiler,{
    publicPath:config.output.publicPath
}));

// Serve the files on port 3000.
app.listen(3000, function () {
    console.log('Example app listening on port 3000!\n');
});

然后,我们添加一个npm srcipt,以便我们更方便地运行服务:
package.json

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "watch": "webpack --watch",
    "start": "webpack-dev-server --open",
    "server":"node server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "clean-webpack-plugin": "^0.1.17",
    "css-loader": "^0.28.7",
    "csv-loader": "^2.1.1",
    "express": "^4.16.2",
    "file-loader": "^1.1.5",
    "html-webpack-plugin": "^2.30.1",
    "parseurl": "^1.3.2",
    "style-loader": "^0.19.0",
    "webpack": "^3.9.1",
    "webpack-dev-middleware": "^1.12.2",
    "webpack-dev-server": "^2.9.5",
    "xml-loader": "^1.2.1"
  },
  "dependencies": {
    "lodash": "^4.17.4"
  }
}

现在,我们运行npm run server,结果如下:

Hash: ad60018b6b26603b9a3a
Version: webpack 3.9.1
Time: 1472ms
          Asset       Size  Chunks                    Chunk Names
  app.bundle.js    1.48 MB    0, 1  [emitted]  [big]  app
print.bundle.js    6.42 kB       1  [emitted]         print
     index.html  256 bytes          [emitted]         
   [0] ./src/print.js 85 bytes {0} {1} [built]
   [1] ./src/index.js 430 bytes {0} [built]
   [2] ./node_modules/.4.17.4@lodash/lodash.js 540 kB {0} [built]
   [3] (webpack)/buildin/global.js 509 bytes {0} [built]
   [4] (webpack)/buildin/module.js 517 bytes {0} [built]
   [5] ./src/style.css 1.04 kB {0} [built]
   [6] ./node_modules/.0.28.7@css-loader!./src/style.css 198 bytes {0} [built]
   [7] ./node_modules/.0.28.7@css-loader/lib/css-base.js 2.26 kB {0} [built]
   [8] ./node_modules/.0.19.0@style-loader/lib/addStyles.js 9.41 kB {0} [built]
   [9] ./node_modules/.0.19.0@style-loader/lib/urls.js 3.01 kB {0} [built]
Child html-webpack-plugin for "index.html":
         Asset    Size  Chunks  Chunk Names
    index.html  544 kB       0  
       [0] ./node_modules/.2.30.1@html-webpack-plugin/lib/loader.js!./node_modules/.2.30.1@html-webpack-plugin/default_index.ejs 546 bytes {0} [built]
       [1] ./node_modules/.4.17.4@lodash/lodash.js 540 kB {0} [built]
       [2] (webpack)/buildin/global.js 509 bytes {0} [built]
       [3] (webpack)/buildin/module.js 517 bytes {0} [built]
webpack: Compiled successfully.

现在,打开浏览器,跳转到 http://localhost:3000,你应该看到你的webpack 应用程序已经运行!

如果想要了解更多关于模块热替换(Hot Module Replacement)的机制,我们推荐你查看模块热替换(Hot Module Replacement)指南

调整文本编辑器

使用自动编译代码时,可能会在保存文件时遇到一些问题。某些编辑器具有“安全写入”功能,可能会影响重新编译。

要在一些常见的编辑器中禁用此功能,请查看以下列表:

Sublime Text 3 - 在用户首选项(user preferences)中添加 atomic_save: "false"。
IntelliJ - 在首选项(preferences)中使用搜索,查找到 "safe write" 并且禁用它。
Vim - 在设置(settings)中增加 :set backupcopy=yes。
WebStorm - 在 Preferences > Appearance & Behavior > System Settings 中取消选中 Use "safe write"。



作者:雨飞飞雨
链接:https://www.jianshu.com/p/3aadbcc32c54
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自blog.csdn.net/sinat_17775997/article/details/80592151
今日推荐