webpack4打包jquery项目

jquery的多页项目,不需要安装依赖,开发阶段也不需要启动本地服务器,直接在浏览器打开,很多情况下用jquery开发还是很方便很快捷的;也会有一些痛点,比如浏览器缓存问题,更新了图片,css或js后,如果引入路径或文件名称不变的话,用户访问的资源可能还是从浏览器缓存获取的旧资源,手动维护文件名称或引入路径又很麻烦,这就需要引入webpack了

webpack4 安装依赖

package.json

"devDependencies": {
  "copy-webpack-plugin": "^5.1.1",
  "css-loader": "^3.4.0",
  "extract-text-webpack-plugin": "^4.0.0-beta.0",
  "file-loader": "^5.0.2",
  "html-loader": "^0.5.5",
  "html-webpack-plugin": "^3.2.0",
  "style-loader": "^1.1.2",
  "url-loader": "^3.0.0",
  "webpack": "^4.41.5",
  "webpack-cli": "^3.3.10",
  "webpack-dev-server": "^3.10.1"
}

多入口

多个页面,就有多个入口,除非有些共性很大的页面可以用同一个入口

entry: {
  index: "./entry/index.js",
  list: "./entry/list.js",
  item: "./entry/item.js"
}

用HtmlWebpackPlugin插件自动生成页面(注:item1.html和item2.html的css和js都相同,使用的是同一个入口item)

plugins: [
  new HtmlWebpackPlugin({
    chunks: [\'index\', \'common\'],
    template: \'./src/index.html\',
    filename: \'index.html\'
  }),
  new HtmlWebpackPlugin({
    chunks: [\'list\', \'common\'],
    template: \'./src/list.html\',
    filename: \'list.html\'
  }),
  new HtmlWebpackPlugin({
    chunks: [\'item\', \'common\'],
    template: \'./src/item1.html\',
    filename: \'item2.html\'
  }),
  new HtmlWebpackPlugin({
    chunks: [\'item\', \'common\'],
    template: \'./src/item2.html\',
    filename: \'item2.html\'
  })
]

jquery项目的资源分类

首先先对项目的资源进行一个分类,不同的种类采用不同的处理方式

  1. css和js
    1. 第三方库的css和js
    2. 多个页面公共的css和js
    3. 单个页面的css和js
  2. 图片
    1. css中的图片
    2. html中的图片(img标签的src,img标签的data-src等等)
  3. 字体文件
种类分析:

【第三方库的css和js】和【字体文件】:这类资源是不会经常改变的,在html的head引入,用CopyWebpackPlugin插件将资源拷贝到最终的目录

new CopyWebpackPlugin([
  {
    from: path.join(__dirname, \'./src/js\'),
    to: path.join(__dirname, \'./dist/js\')
  },
  {
    from: path.join(__dirname, \'./src/css\'),
    to: path.join(__dirname, \'./dist/css\')
  }
])

【多个页面公共的css和js】:这类资源是会变的,直接拷贝会有缓存问题,又因为是公共的,提取出来可以减少页面的重复请求,在入口文件里引入,并用webpack.optimization.splitChunks提取公共部分

optimization: {
  splitChunks: {
    chunks: \'all\',
     cacheGroups: {
       common: {
         name: \'common\',
         minChunks: 2  //最少被2个chunk引用
       }
     }
   }
}

【单个页面的css和js】:在入口文件里引入

// entry/index.js
import \'../src/css/reset.css\'
import \'../src/css/common.css\'
import \'../src/css/index.css\'
import \'../src/css/media.css\'

import common from \'../src/js/common.import\';
common()

【css中的图片】:可直接通过url-loader处理

{ 
  test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/, 
  use: [
    {
      loader: \'url-loader\',
      options: {
        name: \'img/[name].[hash:8].[ext]\', // 输出文件名称
        limit: 1024, // 小于limit则转为base64
        esModule: false, // 禁用esModule, 解决html中img标签的src不正确的问题
        publicPath: \'http://example.com/\' // 项目线上的地址,这里建议用绝对地址,相对地址会在html文件目录结构复杂时出现图片路径问题, 本地开发为http://localhost:8080/
      }
    }
  ]
}

【html中的图片】:对于HtmlWebpackPlugin插件生成的html文件,url-laoder不能直接处理img标签引用的图片,需要用html-laoder处理html文件

{
  test: /\.html$/,
  use: [
    {
      loader: \'html-loader\',
      options: {
        attrs: [\':data-src\', \'img:src\'], // 处理所有data-src属性对应的图片,img标签的src属性对应图片
        interpolate: \'require\' // 启用插值语法,html模版中可以使用require来引入图片,html组件等等
      }
    }
  ]
}

提取css文件

css文件默认是打包在js文件内的,建议提取css文件,从head标签引入

plugins: [
        new ExtractTextPlugin("build/[name].[hash:8].css")
]

本地开发

package.json

{
    "scripts": {
        "dev": "webpack-dev-server"
    }
}
npm run dev

默认端口为8080,访问:http://localhost:8080

生产打包

package.json

{
    "scripts": {
        "build": "webpack"
     }
}
npm run build

完整webpack.config.js

// webpack.config.js
var path = require(\'path\')
var HtmlWebpackPlugin = require(\'html-webpack-plugin\');
var CopyWebpackPlugin = require(\'copy-webpack-plugin\');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
  entry: {
    index: "./entry/index.js",
    teacher: "./entry/teacher.js",
    item: "./entry/item.js",
  },
        output: {
                path: path.join(__dirname, \'./dist\'),
                filename: "build/[name].[hash:8].js"
  },
  module: {
    rules: [
      {
        test: /\.html$/,
        use: [
          {
            loader: \'html-loader\',
            options: {
              attrs: [\':data-src\', \'img:src\'], // 处理所有data-src属性对应的图片,img标签的src属性对应图片
              interpolate: \'require\' // 启用插值语法,html模版中可以使用require来引入图片,html组件等等
            }
          }
        ]
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
      },
      { 
        test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/, 
        use: [
          {
            loader: \'url-loader\',
            options: {
              name: \'img/[name].[hash:8].[ext]\', // 输出文件名称
              limit: 1024, // 小于limit则转为base64
              esModule: false, // 禁用esModule, 解决html中img标签的src不正确的问题
              publicPath: \'http://example.com/\' // 项目线上的地址,这里建议用绝对地址,相对地址会在html文件目录结构复杂时出现图片路径问题, 本地开发为http://localhost:8080/
            }
          }
        ]
      }
    ]
  },
  optimization: {
    splitChunks: {
      chunks: \'all\',
      cacheGroups: {
        common: {
          name: \'common\',
          minChunks: 2,  //最少被2个chunk引用
        }
      }
    }
  },
  plugins: [
    new HtmlWebpackPlugin({
      chunks: [\'index\', \'common\'],
      template: \'./src/index.html\',
      filename: \'index.html\'
    }),
    new HtmlWebpackPlugin({
      chunks: [\'list\', \'common\'],
      template: \'./src/list.html\',
      filename: \'list.html\'
    }),
    new HtmlWebpackPlugin({
      chunks: [\'item\', \'common\'],
      template: \'./src/item1.html\',
      filename: \'item2.html\'
    }),
    new HtmlWebpackPlugin({
      chunks: [\'item\', \'common\'],
      template: \'./src/item2.html\',
      filename: \'item2.html\'
    }),
    new CopyWebpackPlugin([
      {
        from: path.join(__dirname, \'./src/js\'),
        to: path.join(__dirname, \'./dist/js\')
      },
      {
        from: path.join(__dirname, \'./src/css\'),
        to: path.join(__dirname, \'./dist/css\')
      }
    ]),
    new ExtractTextPlugin("build/[name].[hash:8].css")
  ]
  
};