美文网首页
webpack多页应用配置

webpack多页应用配置

作者: 风向应该可以决定发型吧 | 来源:发表于2019-11-15 19:47 被阅读0次

说明: 网上很多教程,大各种各样的内容都有,自己研究的时候查了很多文档,出现了一些错误都一一记录下来.并且配置文件没有任何的封装,旨在能提炼出最关键的内容.

环境

webpack: 4

1. 要用到的插件:

html-webpack-plugin // 用于根据html模板生成页面
clean-webpack-plugin // 用于清除dist目录下的代码
extract-text-webpack-plugin // 用于提取出css到单个或者多个单独文件中

2. 项目目录

 ProjectName
    ├ ─ dist  // 准备发布代码时build出来的文件在这里(需在webpack.config.js中配置)
    ├ ─ node_modules
    ├ ─ src
           ├ ─ css
                  ├ ─ index.css
                  ├ ─ about.css
           ├ ─ js
                  ├ ─ index.js
                  ├ ─ about.js
           ├ ─ pages
                  ├ ─ index.html
                  ├ ─ about.html
    ├ ─ favicon.ico // 可有可无,因为我项目里放了,就写在这里了
    ├ ─ package.json
    ├ ─ webpack.config.js // webpack 配置文件

3. 开始

1. 创建项目
mkdir mutile-page-demo 
cd mutil-page-demo
npm init -y
2. 创建目录
mkdir src
mkdir src/css
mkdir src/js
3. 创建文件(完全可以使用IDE创建出这个目录结构,不一定要使用命令行,我这里只是为了展示起来更直观)
# 注意使用git-bash或Cmder命令行工具,windows命令行中是没有 touch命令的
touch webpack.config.js 
touch ./src/pages/index.html
touch ./src/pages/about.html
touch ./src/css/about.css
touch ./src/css/about.css
touch ./src/js/about.js
touch ./src/js/about.js
4. 下面罗列文件内容,可以自己随便写,也可以copy下面的内容.

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>index</title>
  <link rel="stylesheet" href="../css/index.css">
  <script src="../js/index.js">
  </script>
</head>
<body>
  <div class="title">this is index.html</div>
  <a href="about.html">about</a>
</body>
</html>

about.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>about</title>
  <link rel="stylesheet" href="../css/about.css">
</head>

<body>
  <div class="title">this is about.html</div>
  <a href="index.html">index</a>
</body>

</html>

index.js

window.onload = function () {
  var title = 'index'
  var p = document.createElement('p')
  p.innerText = 'append tag p from index.js!'
  document.body.appendChild(p)
}

about.js

window.onload = function () {
  var p = document.createElement('p')
  p.innerText = 'append tag p from about.js!'
  document.body.appendChild(p)
}

index.css

.title {
  color: red;
}

about.css

.title {
  color: blue;
}
5. 编写配置文件: webpack.config.js

module.exports 中有几个关键点:

  • entry: 入口文件: 简单理解为,webpack从这里开始编译,接受的参数类型
    • 字符串,如: entry: 'index.js' # 配置单页应用

    • 数组, 如: entry: ['index.js', 'about.js']

    • 对象(我使用这种方式): 如:

entry: {
    index: path.resolve(__dirname, 'src/js/index.js'),
    about: path.resolve(__dirname, 'src/js/about.js')
  },
  • output: 用于设置输出文件的配置(build)
  • module: 相关loader配置
  • plugins: 相关插件配置
  • devServer: 开发环境启动的服务,hot reload 在这里配置

直接贴部分代码并说明

entry

entry: {
    index: path.resolve(__dirname, 'src/js/index.js'), // 获得目标文件的绝对路径
    about: path.resolve(__dirname, 'src/js/about.js')
  },

output

path: path.resolve(__dirname, 'dist'), // 将build结果输出到 project 的 dist/ 目录下
filename: 'js/[name]-[hash].bundle.js' // 将js文件输出到 js/ 目录下 

module.rules 配置

module: {
    rules: [{
      test: /\.css$/,
      use: ['style-loader', 'css-loader'] 
    }]
  },

注意 style-loader要卸载css-loader的前面,否测会报错

image.png

plugins配置

new htmlWebpackPlugin({
  filename: 'index.html',  // 生成的html文件名称,可以同时指定输出的路径,如: /pages/index.html,将被输出到 /dist/pages/index.html
  template: path.resolve(__dirname, 'src/pages/index.html'), // 模板位置
  inject: 'head', // 控制webpack把js文件append到html的head还是body中,默认是body
  title: 'index', // 传递title到生成的html中
  chunks: ['index'], // 设置生成的html中要引入哪些js文件: chunk名称需要和entry中的属性保持一致,多个js以数组方式配置,如 chunks: ['index', 'about']
  // favicon: path.resolve('favicon.ico'), // 设置hmtl的shortcut icon
  // minify: { // 启用压缩功能
  //   removeComments: true,  //删除注释
  //   collapseWhitespace: true //删除空格
  // }
}),
new htmlWebpackPlugin({
  filename: 'about.html',
  template: path.resolve(__dirname, 'src/pages/index.html'),
  inject: 'head',
  title: 'about',
  chunks: ['about']
}),
......如果有多个页面需要也这样写

devServer

{
     // 注意设置了此属性将导致hot失效
     // 并且会导致js中通过import引入css出现一些问题
    // openPage: 'src/pages/index.html',

    open: true, // 自动打开浏览器并访问页面
    inline: true, // 内联模式实时刷新,推荐方式
    hot: false, // 热更新,注意当设置为true时,会导致热更新失败,浏览器不再刷新代码,原因不知
    port: 9527,
    host: 'localhost',
    // compress: true, // 启用压缩,会增加服务器端和客户端的负载
  }
6 添加运行代码

在package.json的 scripts 中添加2行代码,保存!

"start": "webpack-dev-server --config webpack.config.js" 
"build": "webpack --config webpack.config.js",

在命令行中执行: npm start

image.png

查看浏览器页面中,发现样式并没有生效
因为webpack中没有像entry那样的节点来单独配置css的输出,所以html中默认的link并不能让webpack帮我们把css文件一起打包

解决方法: 在index.js中import需要的css, webpack的思想是一切皆为模块,所以css也可以通过import引入.

修改index.js为:

import '../css/index.css' # 新增加的一行
window.onload = function () {
  var p = document.createElement('p')
  p.innerText = 'append tag p from index.js!'
  document.body.appendChild(p)
}

保存后查看浏览器发现样式生效了


image.png

然后我们在命令行中执行一下: npm run build
查看procjet中生成了dist目录:

image.png
发现我们预想的css目录没有出现,但是如果查看 由index.js生成的文件末尾(需要格式化一下代码,也可以直接搜索名称为title的样式),会看到 index.css中的代码
image.png

原来webpack把我们的css代码编译到了js中,在打开页面的时候,样式会被追加到html的style标签中.
为了解决这个问题,使用 extract-text-webpack-plugin 插件抽取css

7 使用 extract-text-webpack-plugin 插件抽取css

如果你还未安装此插件,需要安装

cnpm i -D extract-text-webpack-plugin

在webpack.config.js中,添加以下代码

const ExtractTextPlugin = require("extract-text-webpack-plugin");

将 modules.exports rules中 css的配置更改掉:

use: ExtractTextPlugin.extract({
 fallback: "style-loader",
 use: "css-loader"
})


image.png

改为


image.png

在plugins节点中,添加一行

 new ExtractTextPlugin({
    filename: 'css/[name].css'
 })

再次执行 npm run build,得到正确的输出

image.png
8. 如果你仔细看,会发现当你修改过js文件后,再执行 npm run build,会发现 /dist/js 中出现了多个带有不同hash串的 相同文件名. 比如: index-85eb01adecdeb439d2cb.bundle.js 和 index-fe758ed5a5b3da38a76e.bundle.js,见下图.
image.png

这是因为hash的原因,webpack在打包的时候会计算文件的hash值,如果文件被改动,那么整个编译出来的hash串也都会变化.(可以通过下面扩展中说明的chunkhash 和 contenthash来优化output节点中的 filename)
这时,最简单的方法就是build之前先清空掉dist,所以使用了 clean-webpack-plugin 插件

在 webpack.config.js 中加入一行

const {
  CleanWebpackPlugin
} = require('clean-webpack-plugin'); // 文件夹清除工具

并且在plugins节点中增加:

new CleanWebpackPlugin(), // 清空dist文件夹
image.png

扩展:

hash和chunkhash、contenthash区别
hash: hash是跟整个项目的构建相关,只要项目里有文件更改,整个项目构建的hash值都会更改,并且全部文件都共用相同的hash值
chunkhash: chunkhash根据不同的入口文件(Entry)进行依赖文件解析、构建对应的chunk,生成对应的哈希值。我们在生产环境里把一些公共库和程序入口文件区分开,单独打包构建,接着我们采用chunkhash的方式生成哈希值,那么只要我们不改动公共库的代码,就可以保证其哈希值不会受影响。
contenthash: 假设index.js引用了index.css,若使用chunkhash的话,只要js改变,那么css也会被重新构建。如何防止css被重新构建呢?
可以使用extract-text-webpack-plugin提取单独的css文件并使用contenthash,contenthash 只要文件内容不变,那么不会重复构建。

总结:

  1. 通过entry对象方式配置多入口
  2. 通过output将js输出到指定目录
  3. 通过html-webpack-plugin,指定输出多个index.html 页面
  4. 通过webpack-dev-server开启本地服务
  5. 通过import 'xxx.css' 配合 extract-text-webpack-plugin 插件修改,rules配置和在plugins中添加下面代码实现css抽离到单个文件或多个文件
new ExtractTextPlugin({ // 抽离到多个页面
    filename: 'css/[name].css'
  }) 

new ExtractTextPlugin("styles.css") // 抽离到单个页面

遇到的问题:

  1. 执行npm run build时报错
Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead

原因: extract-text-webpack-plugin还不能支持webpack4.0.0以上的版本。
解决方法: 安装最新版本

cnpm install --save-dev extract-text-webpack-plugin@next

发现的问题

  1. 如果plugins中配置了多个目录,并且有多个目录下同时拥有index.html,如果没有配置对应的index.html输出到指定的目录中,那么当npm start时自动打开的首页面是 new htmlWebpackPlugin()写在最后的一个页面,
    比如:
new htmlWebpackPlugin({
      template: path.resolve(__dirname, 'src/pages/zh-CN/index.html'),
      inject: 'head',
      title: 'index',
      chunks: ['index'],
      favicon: path.resolve('favicon.ico'),
      filename: 'index.html',
    }),
new htmlWebpackPlugin({
      template: path.resolve(__dirname, 'src/pages/zh-TW/index.html'),
      inject: 'head',
      title: 'index',
      chunks: ['index'],
      favicon: path.resolve('favicon.ico'),
      filename: 'index.html',
    }),
new htmlWebpackPlugin({
      template: path.resolve(__dirname, 'src/pages/test/index.html'),
      inject: 'head',
      title: 'index',
      chunks: ['index'],
      favicon: path.resolve('favicon.ico'),
      filename: 'index.html',
    }),

原因大概是,最后根据src/pages/test/index.html生成的index.html把前面的覆盖了.

  1. 当给devServer设置了 openPage: 'src/pages/zh-CN/index.html' 时,会导致hot失效,并且js中通过import引入css也会出现一些问题,并在浏览器中报错.

参考文档:

  1. https://blog.csdn.net/joyce_lcy/article/details/78627268#1-%E5%AE%89%E8%A3%85%E6%8F%92%E4%BB%B6
  2. https://segmentfault.com/a/1190000011434481?utm_source=tag-newest

相关文章

  • webpack4 构建vue多页工程

    webpack4 构建vue多页工程 多页应用开发环境配置 构建开发环境的配置,需要使用到webpack-dev-...

  • 9、webpack多页应用

    webpack支持多页应用,需要配置入口和出口 1、入口配置 2、出口配置 3、 插件配置 webpack.con...

  • webpack 入门 2

    多页应用打包 例如 webpack.config.js 内容 7.resolve 配置(webpack 如何寻找模...

  • webpack4构建多页应用,了解一下

    用webpack构建多页应用可以有2种思路,多页面单配置 vs. 多页面多配置。本例子采用多页面单配置,即在单页应...

  • webpack多页应用配置

    说明: 网上很多教程,大各种各样的内容都有,自己研究的时候查了很多文档,出现了一些错误都一一记录下来.并且配置文件...

  • webpack常用配置

    这里记录一下webpack常用配置打包多页应用 html-webpack-plugin loader 让 webp...

  • html-webpack-plugin

    webpack 配置多页面应用 引用 webpack.config.js 配置

  • 前端工程之多页面webpack打包模板

    如何配置一个多页应用webpack工程化模板? webpack的四个核心概念: entry 入口:从哪里开始 ou...

  • 2018-03-21

    react webpack 多页面应用的配置 项目的目录结构 webpack 配置文件 目录 webpack....

  • Webpack高级

    1.多页应用打包 在webpack.config.js中修改入口和出口配置 // 1. 修改为多入口 entr...

网友评论

      本文标题:webpack多页应用配置

      本文链接:https://www.haomeiwen.com/subject/jkpsictx.html