webpack 之单页面打包

1,577 阅读4分钟

上一篇文件简单的介绍的一些webpack的基础知识和简单应用以及部分loader的使用,今天将会介绍一些loader和plugins常见插件配置,下篇文章将会介绍多页面打包配置

在现在工程化开发的今天比如会使用一些工程化语言帮助我们快速开发,减少时效性例如,less scss等css预处理语言,那么我们就来说说怎么样在webpack中配置。

// 依然新建一个文件

webpack-2
	-- src
            -- img   // 图片音频视频等文件
            -- css   // .css/.scss/.less 文件 
            -- html  // 模板文件
                    template.html
            -- js
                header.js	 // 头部
                sidebar.js 	 // 侧边栏	
                content.js 	 // 内容區域 
                index.js 	// 入口文件
            
js 目录下
// index.js
import {createHeader} from "./header";
import {createContent} from "./content";
import {createSidebar} from "./sidebar";
import '../css/overall.css'  // 引进css文件
import '../css/index.scss'

let root = document.querySelector('body');

createHeader(root);
createSidebar(root);
createContent(root)
// header.js
import '../css/header.css'

export const createHeader = (root) => {
  let eleDiv = document.createElement('div');
  eleDiv.innerText = '我是头部';
  root.appendChild(eleDiv);
}
// sidebar.js
export const createSidebar = (root) => {
  let eleSidebar = document.createElement('div');
  eleSidebar.innerText = '我是侧边栏区域'
  root.appendChild(eleSidebar);
}
// content.js
import imgUrl from '../img/682626.png'
import '../css/content.css'

export const createContent = (root) => {
  let eleDiv = document.createElement('div');
  eleDiv.innerText = '我是内容区域'
  let eleImg = document.createElement('img')
  eleImg.src = imgUrl;
  root.appendChild(eleDiv)
  root.appendChild(eleImg)
}
css 目录下
// content.css
img {
    width: 300px;
}
// header.css
div {
    width: 100%;
    height: 60px;
    background: blueviolet;
}
// overall.css
* {
    padding: 0;
    margin: 0;
}
body {
    background: antiquewhite;
}
// index.scss
div {
  background: blue;
  display: flex;
    div {
      border: aqua 1px solid;
    }
}
html 目录下
// template.html 模板文件可以写 esj
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title><%= htmlWebpackPlugin.options.title %></title> 
</head>
<body>
    <div>我是模板里面的div内容</div>
</body>
</html>

在如今工程化开发项目的环境下,必然会使用多种工程化语言 例如less sass 等 那webpack依然需要对这些进行配置处理,首先我们就要先安装

npm install flie-loader --save-dev // 处理文件

npm install url-loader --save-dev // 处理图片

npm install css-loader --save-cssdev // 处理css 文件之间的关系,并打包成一段css代码

npm install sacc-loader --save-dev // 处理sass文件

npm install node-sass --save-dev // 处理sass文件编译成css文件

npm install style-loader --save-dev // 将处理完合并成一段的css通过style标签插入head中

npm install postcss-loader --save-dev // 处理css前缀兼容 必须依赖autoprefixer

npm install autoprefixer --save-dev

基本配置如下
// webpack.config.js
const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin'); // 在打包结束之后自动生成一个html文件 并且引入生产的js文件
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 需要注意的是,经过版本升级之后以及不是默认导出了,而是导出一个方法

module.exports = {
  mode: 'development', // 本地开发模式 不压缩代码
  devtool: "source-map", // 默认是none ,sourceMap 就是一种引射关系,它能将最终打包后出错的代码所在源文件信息展示出来
  entry: './src/js/index.js', // 入口文件
  output: {
    filename: 'main.js', // 被打包之后的入口文件的名字
    path: path.resolve(__dirname, 'build') // 打包之后的文件夹
  },
  module: {  // webpack loader 的配置规则
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: {
          loader: "url-loader", // 限制文件大小,例如图片 小图片处理成 base64 大图片原封不动
          options: {
            outputPath: 'images/',
            limit: 2048 // 小于8192字节就解析成base 64,大于就直接打包成文件
          }
        }
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2)$/, // 处理字体文件
        use: [
          {
            loader: "file-loader", // 处理文件打包位置
            options: {
              name: '[name].[ext]',
              outputPath: 'font'
            }
          }
        ]
      },
      {
        test: /\.(css|scss)$/,  // 必须按以下顺序
        use: [
            'style-loader', // 将css通过style标签插入到head当中
            {
              loader: "css-loader", // 解析多个css关系,最好合并成一段css
              options: {
                importLoaders: 2 // 表示通过import语法引入的文件也需要走下面的loader处理
              }
            },
            'sass-loader', // 解析sass文件
            'postcss-loader' // 自动css兼容前缀  autoprefixer
        ]
      }
    ]
  }
}
postcss-loader 的配置

需要在根目录中新建postcss.config.js 配置文件

module.exports = {
  plugins: [
      require('autoprefixer')
  ]js
}

在package.josn 配置需要兼容的浏览器

  "browserslist": [
    "last 1 version",
    "> 1%",
    "IE 10"
  ]

当然,我们依然会使用一些webpack的插件

npm install clean-webpack-plugin --save-dev 每次打包先删除之前打包好的文件

npm install html-webpack-plugin --save-dev html 模板文件,并支持写 ejs语法

webpack.config.js 配置内容如下

const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin'); // 在打包结束之后自动生成一个html文件 并且引入生产的js文件
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 需要注意的是,经过版本升级之后以及不是默认导出了,而是导出一个方法

module.exports = {
  mode: 'development', // 本地开发模式 不压缩代码
  devtool: "source-map", // 默认是none ,sourceMap 就是一种引射关系,它能将最终打包后出错的代码所在源文件信息展示出来
  entry: './src/js/index.js', // 入口文件
  output: {
    filename: 'main.js', // 被打包之后的入口文件的名字
    path: path.resolve(__dirname, 'build') // 打包之后的文件夹
  },
  module: {  // webpack loader 的配置规则
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: {
          loader: "url-loader", // 限制文件大小,例如图片 小图片处理成 base64 大图片原封不动
          options: {
            outputPath: 'images/',
            limit: 2048 // 小于8192字节就解析成base 64,大于就直接打包成文件
          }
        }
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2)$/, // 处理字体文件
        use: [
          {
            loader: "file-loader", // 处理文件打包位置
            options: {
              name: '[name].[ext]',
              outputPath: 'font'
            }
          }
        ]
      },
      {
        test: /\.(css|scss)$/,
        use: [
            'style-loader', // 将css通过style标签插入到head当中
            {
              loader: "css-loader", // 解析多个css关系,最好合并成一段css
              options: {
                importLoaders: 2 // 表示通过import语法引入的文件也需要走下面的loader处理
              }
            },
            'sass-loader', // 解析sass文件 
            'postcss-loader' // 自动css兼容前缀  必须搭配 autoprefixer
        ]
      }
    ],
    plugins: [
        new htmlWebpackPlugin({
             title: 'My App', // 模板文件允许写 ejs 语法
          template: "scr/html/template.html", // 模板路径
          filename: 'index.html'
        }),
        new CleanWebpackPlugin()
    ]
  }
}

我们需要优化css的文件

// webpack.config.js
// MiniCssExtractPlugin 提取 JS 中引入的 CSS 打包到单独文件中,然后通过标签 <link>添加到头部;style-loader 则是通过 <style> 标签直接将 CSS 插入到 DOM 中

// 把css代码打包成一个css文件 并通过link标签引入
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 
// 主要用来优化css文件的输出,默认使用cssnano,其优化策略主要包括:摈弃重复的样式定义、砍掉样式规则中多余的参数、移除不需要的浏览器前缀等
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin'); 

  plugins: [
      new MiniCssExtractPlugin({
            filename:'css/index.css'
        }),
      new OptimizeCssAssetsPlugin({
        assetNameRegExp: /\.css$/g,
        cssProcessorOptions: {
          safe: true,
          autoprefixer: { disable: true }, // 这里是个大坑,稍后会提到
          mergeLonghand: false,
          discardComments: {
            removeAll: true // 移除注释
          }
        },
        canPrint: true
      })
	]

前文我们提到这里有个大坑 就是把我们通过autoprefixer加好了前缀给移除了 于是便有了这段配置autoprefixer: { disable: true },禁用掉cssnano对于浏览器前缀的处理。

sourceMap

就是一种映射关系,他能将最终打包后出错的代码所在的原始文件信息展示出来

不同的关键词所代表的的基本含义

  • cheap: 只处理业务代码的错误信息, 其他的引用模块或是loader的错误予以忽略
  • inline:把生成的.map文件编码成base64格式, 内嵌到最后生成的js文件中
  • module:也处理module或是loader里面的错误信息
  • source-map:生成一个.map文件
  • eval:以eval的方式来处理业务代码, 以方便吧代码和原始文件地址进行管理

建议在development的模式下, 采用cheap-module-eval-source-map 建议在production的模式下,采用cheap-module-source-map

至此整个webpack.config.js 文件配置如下

const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin'); // 在打包结束之后自动生成一个html文件 并且引入生产的js文件
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 需要注意的是,经过版本升级之后以及不是默认导出了,而是导出一个方法

// MiniCssExtractPlugin 提取 JS 中引入的 CSS 打包到单独文件中,然后通过标签 <link>添加到头部;style-loader 则是通过 <style> 标签直接将 CSS 插入到 DOM 中
// 把css代码打包成一个css文件 并通过link标签引入
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 主要用来优化css文件的输出,默认使用cssnano,其优化策略主要包括:摈弃重复的样式定义、砍掉样式规则中多余的参数、移除不需要的浏览器前缀等
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = {
  mode: 'development', // 本地开发模式 不压缩代码
  devtool: "source-map", // 默认是none ,sourceMap 就是一种引射关系,它能将最终打包后出错的代码所在源文件信息展示出来
  entry: './src/js/index.js', // 入口文件
  output: {
    filename: 'main.js', // 被打包之后的入口文件的名字
    path: path.resolve(__dirname, 'build') // 打包之后的文件夹
  },
  module: {  // webpack loader 的配置规则
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: {
          loader: "url-loader", // 限制文件大小,例如图片 小图片处理成 base64 大图片原封不动
          options: {
            outputPath: 'images/',
            limit: 2048 // 小于8192字节就解析成base 64,大于就直接打包成文件
          }
        }
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2)$/, // 处理字体文件
        use: [
          {
            loader: "file-loader", // 处理文件打包位置
            options: {
              name: '[name].[ext]',
              outputPath: 'font'
            }
          }
        ]
      },
      {
        test: /\.(css|scss)$/,
        use: [
            // 'style-loader', // 将css通过style标签插入到head当中
            MiniCssExtractPlugin.loader,
            {
              loader: "css-loader", // 解析多个css关系,最好合并成一段css
              options: {
                importLoaders: 2 // 表示通过import语法引入的文件也需要走下面的loader处理
              }
            },
            'sass-loader', // 解析sass文件
            'postcss-loader' // 自动css兼容前缀 必须搭配 autoprefixer
        ]
      }
    ]
  },
  plugins: [
    new htmlWebpackPlugin({
      title: 'My App', // 模板文件允许写 ejs 语法
      template: "./src/html/template.html", // 模板路径
      filename: 'index.html',
      minify: false // 是否压缩
    }),
    new CleanWebpackPlugin(), // 删除上次一次打包的文件
    new MiniCssExtractPlugin({
      filename:'css/index.css'
    }),
    new OptimizeCssAssetsPlugin({
      assetNameRegExp: /\.css$/g,
      cssProcessorOptions: {
        safe: true,
        autoprefixer: { disable: true }, // 这里是个大坑,稍后会提到
        mergeLonghand: false,
        discardComments: {
          removeAll: true // 移除注释
        }
      },
      canPrint: true
    })
  ]
}

下篇讲述多页打包,敬请期待