webpack基本使用,打包 html多页面 scss预处理器 autoprefixer浏览器前缀 使用jquery,代码压缩,命令行自动生成html和js

9 篇文章 0 订阅
4 篇文章 0 订阅

webpack基本使用,打包html,scss预处理器,autoprefixer浏览器前缀,使用jquery,代码压缩,命令行自动生成html和js

项目git地址-https://github.com/zshuai34/webpack3-Multi-html-pages

本文基本内容介绍

学习使用webpack打包 html多页面文件时,整理的webpack使用方法

  • 打包单个js文件,生成hash文件名;
  • 使用html-webpack-plugin打包html
  • css-loader打包css,安装使用 scss预处理器,使用Autoprefixer添加浏览器css前缀
  • webpack中使用jquery方法
  • 命令行生成html&js
  • 最后有完整的webpack配置
    • 完整webpack.config.js 配置
    • 完整的package.json
    • postcss.config.js

学习webpack中,一些解决方法来自网络

在这里插入图片描述


安装

// 全局安装webpack
npm i webpack -g

// 项目中安装

npm i webpack webpack-cli webpack-dev-server -D

打包基本使用

打包js
// 打包单个js
const path = require('path');
module.exports = {
  entry: './js/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  }
};
// 打包多个js为一个js
const path = require('path');
module.exports = {
  entry: [
    index: './js/index',
	index2: './js/index2'
  ],
  output: {
    path: __dirname + '/dist/js',
    filename: '[name].js' 
    // name:js原名称 /hash随机hash值 /chunkhash:只要文件没有改变,就不会生成新的hash  
  }
};
babel对es6代码进行转换

npm i babel-cli@6.26.0 babel-loader@6.26.0 babel-core@7.1.4 babel-preset-env@1.6.1 -D

{//js loader
    test: /\.js$/,
    exclude: /(node_modules|bower_components)/,
    use: {
       oader: 'babel-loader'
    }
}
打包html

使用 html-webpack-plugin 插件

var path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: {
	index: './js/index',
	index2: './js/index2'
  },
  output: {
    path: __dirname + '/dist/js',
    filename: '[name].js' // 随机名称 hash /chunkhash:只要文件没有改变,就不会生成新的hash  
  },
  plugins: [
    new HtmlWebpackPlugin({
		title: '首页',
		template: 'index.html', // 源模板文件
		filename: __dirname + '/dist/index.html', // 输出文件
		hash: true, // 添加webpack每次编译产生的唯一hash值  js?jskadjsjd
		inject: 'body', // 向template或者templateContent中注入所有静态资源,不同的配置值注入的位置不经相同。
		chunks: ['index'] //在配置多个页面时,每个页面注入的cthunk应该是不相同的,需要通过该配置为不同页面注入不同的cthunk;
	}),
	new HtmlWebpackPlugin({
		title: '我的页面2',
		template: 'index2.html',
		filename: __dirname + '/dist/index2.html',
		chunks: ['index2']
	})
  ]
}
打包图片

安装 url-loader
npm i url-loader@1.1.2 -D
如果图片大小超过设置的转换base64限制,就需要安装 npm i file-loader@6.1.1 -D,否则会报错

{// img 压缩,,生成hash值
  test: /\.(png|svg|jpg|gif)$/,
    use: [
      {
       loader: 'url-loader',
        options: {
          esModule: false,
           limit: 1024 * 50, // 50KB以上压缩
           outputPath: './img',
           name: '[name].[hash:8].[ext]'
        }
      }
    ]
}

需要对页面中引入的图片进行特殊处理
安装html-withimg-loader
npm i html-withimg-loader@0.1.16 -D

module: {
 rules: [
   {
     test: /\.(html)$/,
     loader: 'html-withimg-loader',
   }
 ]
}

package.json 中依赖包

新建空文件夹,cmd命令执行 npm init 自动生成 package.json文件,粘贴 devDependenciespackage.json中,执行 npm install 安装依赖包

  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.4",
    "babel-preset-env": "^1.6.1",
    "clean-webpack-plugin": "^0.1.19",
    "css-loader": "^0.28.10",
    "expose-loader": "^0.7.5",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^1.1.11",
    "html-webpack-inline-source-plugin": "0.0.10",
    "html-webpack-plugin": "^3.0.6",
    "jquery": "^1.11.3",
    "open-browser-webpack-plugin": "0.0.5",
    "style-loader": "^0.20.3",
    "uglifyjs-webpack-plugin": "^1.2.3",
    "url-loader": "^1.0.1",
    "webpack": "^3.5.5",
    "webpack-dev-server": "^1.14.1"
  }
  • babel js语法: es6 => es5

    • npm install -D babel-loader @babel/core @babel/preset-env webpack
  • clean-webpack-plugin 构建时删除构建目录

  • css-loader 必须要配合使用style-loader,css-loader的作用是帮我们分析出各个css文件之间的关系,把各个css文件合并成一段css;

  • style-loaderstyle-loader的作用是将css-loader生成的css代码挂载到页面的header部分,多个loader配合使用时,处理顺序是:从下到上,从右到左 的顺序

  • expose-loader暴露全局属性方法,例如jquery

  • extract-text-webpack-plugin为了抽离css样式,防止将样式打包在js中引起页面样式加载错乱的现象在webpack4中,建议用mini-css-extract-plugin替代

  • file-loader打包图片,字体等文件,生成一个随机的hash值作为图片的名字

  • html-webpack-inline-source-plugin依赖于html-webpack-plugin

    • npm i -D html-webpack-inline-source-plugin html-webpack-plugin
  • html-webpack-plugin 打包html,把 js、css 等代码内联进 html 中

    new htmlWebpackPlugin({ //有几个生成new几个html,生成html
          filename: 'index.html',
          title: '首页',
          template: 'index.html',
          chunks: ['app', 'flexible75'],//html需要引入的js
          cache: true,//只有在内容变化时才会生成新的html
          minify: {
            removeComments: true, //是否压缩时 去除注释
            collapseWhitespace: false // 去除空格压缩
          }
        })
    
  • jquery引入的jquery js

  • open-browser-webpack-plugin 自动打开浏览器插件

  • uglifyjs-webpack-plugin 代码压缩插件

  • url-loader类似 file-loader

  • webpack-dev-server一个服务器插件,相当于webpack+apache,启动一个web服务并实时更新修改

问题:html中img src引入图片不打包

解决方法:使用 html-withimg-loader

npm - html-withimg-loader

webpack.config.js中配置

module: {
    rules: [
      {
        test: /\.(html)$/,
        loader: 'html-withimg-loader',
      }
    ],
  }

使用scss

npm - sass-loader

安装scss

安装css和sass插件
npm install sass-loader@7.3.1 node-sass@4.14.1 css-loader@0.28.10 expose-loader@0.7.5 style-loader@0.20.3 --save-dev
如果出现报错 Module build failed: ReferenceError: window is not defined,则降低sass版本

  • 先卸载 npm uninstall sass-loader
  • 再安装 npm install sass-loader@7.3.1 --save-dev

webpack.config.js配置

官方方法:

module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          // Creates `style` nodes from JS strings
          'style-loader',
          // Translates CSS into CommonJS
          'css-loader',
          // Compiles Sass to CSS
          'sass-loader',
        ],
      },
    ],
  }

使用extract-text-webpack-plugin

提取css样式,通过link方式引入html中
npm i extract-text-webpack-plugin@3.0.2 -D

module: {
    rules: [
      {//css loader
        test: /\.(css|s[ac]ss)$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'sass-loader']
        })
      }
    ]
}

使用 autoprefixer

Autoprefixer解析CSS文件并且添加浏览器前缀到CSS规则里,使用Can I Use的数据来决定哪些前缀是需要的。

安装autoprefixer

npm - autoprefixer

npm i autoprefixer@9.8.6 -D

根目录新建postcss.config.js 文件

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

webpack.config.js配置

{//css loader
    test: /\.(css|s[ac]ss)$/,
        use: ExtractTextPlugin.extract({
            fallback: 'style-loader',
            use: ['css-loader', 'sass-loader', 'postcss-loader']
        })
}

package.json配置

"browserslist": [
    "defaults",
    "not ie < 11",
    "last 2 versions",
    "> 1%",
    "iOS 7",
    "last 3 iOS versions"
  ]

安装jquery

npm安装jquery

npm i jquery@1.11.3 -S
在页面js中通过 var jquery = require('jquery')引入
此方法会在所有使用jquery的js 中都会打包进jquery

webpack.config.js

module: {
    rules: [
        {
        test: require.resolve('jquery'),
        use: [{
          loader: 'expose-loader',
          options: 'jQuery'
        },{
          loader: 'expose-loader',
          options: '$'
        }]
      }
    ]
},
plugins: [
    // 全局引入jquery
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
    }),
]

CND引入jquery

建议在页面中通过CDN方式引入jquery

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.11.3/jquery.min.js"></script>

命令行生成html&js

安装依赖包

babel-node 是 babel-cli 的附带工具,所以只要安装了 babel-cli ,就可以直接使用 babel-node

  • 安装babel-clinpm i babel-cli -D
  • 安装readnpm i read -D
  • 安装 colorsnpm i colors -D

package.jsonscripts添加 new命令

"scripts": {
    "new": "babel-node build/new-page.js"
}

build目录

-build
  - templates // 页面模板
	- page-new.html // html模板,按自己需求写入,如:CDN引入jquery
    - page-new.js // js模板,按自己需求写入
  - new-page.js // 生成页面模板命令方法

new-page.js

#!/usr/bin/env node
const fs = require('fs')
const path = require('path')
const read = require('read')
require('colors')

const fileCharset = 'utf-8'
let pageTitle = ''
let pageName = null
let flagCount = 2

const waitForPageTitle = (prompt) => {
  read({
    prompt: prompt || '请输入新增页面标题 : ',
    timeout: 60000
  }, (error, result, isDefault) => {
    if (error) {
      if (error.message === 'canceled') {
        console.log('\n\n您已取消该操作!'.yellow)
        process.exit(0)
      } else if (error.message === 'timed out') {
        console.log('等待已超时, 请重新输入!'.yellow)
        process.exit(0)
      } else {
        throw error
      }
    }
    if (result && result !== '') {
      pageTitle = result
    }
    waitForPageName()
  })
}
waitForPageTitle()

const waitForPageName = (prompt) => {
  read({
    prompt: prompt || '请输入新增页面文件名: ',
    timeout: 60000
  }, (error, result, isDefault) => {
    if (error) {
      if (error.message === 'canceled') {
        console.log('\n\n您已取消该操作!')
        process.exit(0)
      } else if (error.message === 'timed out') {
        console.log('等待已超时, 请重新输入!')
        process.exit(0)
      } else {
        throw error
      }
    }
    if (!result || result === '') {
      waitForPageName('页面文件名不能为空,请重新输入: '.yellow)
    } else {
      pageName = result
      validPageName()
    }
  })
}

const validPageName = () => {
  const projectRoot = path.resolve(__dirname, '../')
  const pageDir = path.resolve(projectRoot, `./src/pages/${pageName}`)
  const exists = fs.existsSync(pageDir)
  if (exists) {
    console.log(`该页面已存在:  ${pageDir}`.yellow)
    waitForPageName('请重新输入新增页面文件名:')
  } else {
    fs.mkdirSync(pageDir)
    createPage(projectRoot, pageDir, pageName)
  }
}

const createPage = (projectRoot, pageDir, pageName) => {
  const sourceHtml = path.resolve(projectRoot, 'build/templates/page-new.html')
  const sourceJS = path.resolve(projectRoot, 'build/templates/page-new.js')
  const destHtml = path.resolve(pageDir, `${pageName}.html`)
  const destJS = path.resolve(pageDir, `${pageName}.js`)
  copyFile(sourceHtml, destHtml, (destFile) => {
    flagCount--
    ensureSuccess()
  })
  copyFile(sourceJS, destJS, (destFile) => {
    flagCount--
    ensureSuccess()
  })
}

const ensureSuccess = () => {
  if (flagCount === 0) {
    const tip = `${pageName} 页面新增成功! 标题为:  ${pageTitle}`
    console.log(tip.green)
    // 页面生成成功提示
    const tipConfig = '请在webpack.config.js中配置 pagesEntryHtml和 pagesEntryJs 来打包html和js'
    console.log(tipConfig.green)
    process.exit(0)
  }
}

const copyFile = (source, dest, cb) => {
  fs.readFile(source, fileCharset, (err, data) => {
    if (err) throw err
    data = data.replace(/\${TITLE}/g, pageTitle)
    fs.writeFile(dest, data, fileCharset, (err) => {
      if (err) throw err
      cb(dest)
    })
  })
}

page-new.html

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=EDGE"/>
	<meta name="viewport" content="initial-scale=1, user-scalable=no, width=device-width">
	<meta name="format-detection" content="telephone=no">
	<meta http-equiv="Pragma" content="no-cache">
	<title>${TITLE}</title>
</head>

<body>
${TITLE}
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
</body>

</html>

page-new.js

/**
 * @author zs
 * 在此js中引入页面私有的css文件
 */
console.log('~_~ jQuery can use directly ~_~')
console.log(jQuery)
console.log('add your code here ....')

完整的webpack配置

项目目录

- dist // 打包后的文件
- src  // 开发目录
	- css // 可以使用css/scss
		- main.scss
		- about.css
	- img
    - js
	- pages // 页面文件
		- about
			- about.html
			- about.js
		- index.html
- package.json
- package-lock.json
- postcss.config.js // autoprefixer 配置文件
- webpack.config.js	// webpack配置

webpack.config.js 配置

var webpack = require('webpack');
var path = require('path');
var htmlWebpackPlugin = require('html-webpack-plugin');
var cleanWebpackPlugin = require('clean-webpack-plugin');
var uglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
// var OpenBrowserPlugin = require('open-browser-webpack-plugin');
/**
 * html-webpack-plugin 构建HTML文件
 * clean-webpack-plugin 构建时清空 build目录
 * uglifyjs-webpack-plugin 代码压缩插件
 * extract-text-webpack-plugin 抽离css样式,防止将样式打包在js中引起页面样式加载错乱的现象
 * open-browser-webpack-plugin 自动打开浏览器插件
 */
const pagesPath = './src/pages/'

devWebpackConfig = {
  entry: { //入口
    app: './src/app.js',
    common: [
      './src/js/flexible75.js'
    ]
  },
  output: {//出口
    path: path.resolve(__dirname, 'dist'), // URL 以 HTML 页面为基准
    publicPath: '',//cdn 按需加载或加载外部资源
    filename: 'js/[name].[hash].js'
  },
  devServer: { //服务
    contentBase: './dist', // 告诉服务器从哪里提供内容。只有在你想要提供静态文件时才需要。
    host: 'localhost',
    hot: true, // 启用 webpack 的模块热替换特性
    inline: true, //推荐使用模块热替换的内联模式
    progress: true,//显示打包速度
    port: 8081,
    proxy: {//代理
      "/api": {//请求api下的接口都会被代理到 target: http://xxx.xxx.com 中
        target: 'http://aixiaiodou.cn:3000',
        changeOrigin: true,
        secure: false,// 如果是 https,需要配置
        pathRewrite: {'^/api': ''}, // 如果不想使用/api 可以重写
        bypass: function (req, res, proxyOptions) {
          if (req.headers.accept.indexOf('html') !== -1) {
            console.log('Skipping proxy for browser request.');
            return '/index.html';
          }
        }
      }
    }
  },
  module: {
    rules: [
      {//css loader
        test: /\.(css|s[ac]ss)$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'sass-loader', 'postcss-loader']
        })
      },
      {//js loader
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader'
        }
      },
      {// img 压缩,,生成hash值
        test: /\.(png|svg|jpg|gif)$/,
        use: "file-loader?name=[name][hash].[ext]&publicPath=../img/&outputPath=./img"
        /*name=[name].[ext]文件名,publicPath=../css中路径,outputPath=./img打包后的生成地址*/
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: ['file-loader']
      },
      {
        test: /\.(html)$/,
        loader: 'html-withimg-loader',
      }
    ]
  },
  devtool: 'cheap-module-eval-source-map', // 转换过的代码
  plugins: [
    // new htmlWebpackPlugin({ //有几个生成new几个html,生成html
    //   filename: 'index.html',
    //   title: '首页',
    //   template: pagesPath + 'index.html',
    //   chunks: ['app'],//html需要引入的js
    //   cache: true,//只有在内容变化时才会生成新的html
    //   minify: {
    //     removeComments: true, //是否压缩时 去除注释
    //     collapseWhitespace: false // 去除空格压缩
    //   }
    // }),
    new cleanWebpackPlugin(['dist']), //构建时清除dist目录
    // 全局引入jquery
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
    }),
    new uglifyjsWebpackPlugin(),
    new ExtractTextPlugin({ //提取css
      filename: 'css/[name].[hash].css',
      disable: false,

      allChunks: true
    }),
    new webpack.optimize.CommonsChunkPlugin({ //打包公共js
      name: 'common',
      chunks: ['./src'],
      minChunks: 2,
      minChunks: Infinity
    }),
    new webpack.HashedModuleIdsPlugin()
    // new OpenBrowserPlugin({ url: 'http://localhost:8081'}) //自动打开浏览器
  ]
};
/**
 * 公共js放到 app.js 中
 * 要添加页面私有js,添加后在htmlWebpackPlugin-chunks中添加即可
 * 如果需要添加样式,在私有js中require
 * @type {string[]}
 */
const pagesEntryJs = ['about']
pagesEntryJs.map(pJs => {
  devWebpackConfig.entry[pJs] = `${pagesPath + pJs}/${pJs}.js`
})

/**
 * 要添加的页面
 * filename:文件名称
 * template:页面路径
 * chunks: [] 页面引入的私有js,需要在devWebpackConfig-entry中配置,  common为公共js包括:【flexible75】
 * title: 页面标题 <%= htmlWebpackPlugin.options.title %>
 * @type {({template: string, filename: string, chunks: [string], title: string}|{template: string, filename: string, chunks: [string, string], title: string})[]}
 */
const pagesEntryHtml = [
  {filename: 'index', template: 'index', chunks: ['common', 'app']},
  {filename: 'about', template: 'about/index', chunks: ['common', 'app', 'about']}
]
pagesEntryHtml.map(page => {
  const plugin = new htmlWebpackPlugin({
    // title: page.title,
    filename: page.filename + '.html',
    template: pagesPath + page.template + '.html',
    chunks: page.chunks,
    cache: true, //只有在内容变化时才会生成新的html
    minify: {
      removeComments: true, //是否压缩时 去除注释  生产环境部署时,可以压缩去掉空格和注释
      collapseWhitespace: false // 压缩去除空格和换行符
    }
  })
  devWebpackConfig.plugins.push(plugin)
})


module.exports = devWebpackConfig

完整的package.json

{
  "name": "webpack3",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "watch": "webpack --watch",
    "build": "webpack",
    "dev": "webpack-dev-server --hot --inline --open"
  },
  "keywords": [],
  "author": "zs",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^9.8.6",
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.4",
    "babel-preset-env": "^1.6.1",
    "clean-webpack-plugin": "^0.1.19",
    "css-loader": "^0.28.10",
    "expose-loader": "^0.7.5",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^1.1.11",
    "html-webpack-inline-source-plugin": "0.0.10",
    "html-webpack-plugin": "^3.0.6",
    "html-withimg-loader": "^0.1.16",
    "open-browser-webpack-plugin": "0.0.5",
    "postcss-loader": "^3.0.0",
    "sass": "^1.26.10",
    "sass-loader": "^7.3.1",
    "style-loader": "^0.20.3",
    "uglifyjs-webpack-plugin": "^1.2.3",
    "url-loader": "^1.0.1",
    "webpack": "^3.12.0",
    "webpack-dev-server": "^1.14.1"
  },
  "browserslist": [
    "defaults",
    "not ie < 11",
    "last 2 versions",
    "> 1%",
    "iOS 7",
    "last 3 iOS versions"
  ],
  "dependencies": {
    "jquery": "^1.11.3"
  }
}

postcss.config.js

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

注:

  • 基本配置来自 webpack3,对此配置进行的一些优化,包括打包html,和entry中打包的js文件
  • 命令行生成页面方法来自 QuickStart-jQuery-webpack
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值