webpack(一)

200 阅读3分钟

webpack

yarn init
yarn add webpack webpack-cli --dev
yarn webpack --version
yarn webpack

webpack.config.js

const path = require('path')
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'output')
  }
}
// yarn webpack --mode development
// yarn webpack --mode none
1.webpack资源模块加载
// yarn add css-loader --dev
// yarn add style-loader --dev  把css-loader转换后的结果通过style标签的形式最加到页面上
// yarn add file-loader --dev 文件资源加载器
// yarn add url-loader --dev URL加载器 (小文件转为baseURL)
2.webpack常用加载器分类
  • 编译转换类
  • 文件操作类
  • 代码检查类
3.webpack与es2015
// yarn add babel-loader @babel/core @babel/preset-env --dev
  • webpack只是打包工具
  • 加载器可以用来编译转换代码
4.webpack加载资源的方式
  • 遵循ES Module标准的import声明
  • 遵循CommomJS标准的require函数
  • 遵循AMD标准的define函数和require函数
  • loader加载的非JavaScript也会触发资源加载
  • 样式代码中的@import指令和url函数
  • HTML代码中图片标签的src属性
// yarn add html-loader --dev
5.webpack核心工作原理

loader机制是webpack的核心

6.webpack开发一个loader
// src/about.md
# ZXT

// src/main.js
import about from './about.md'
console.log(about)

// markdown-loader.js   返回一个js
//  __webpack_exports__["default"] = ("<h1 id="zxt">ZXT</h1>\n");
const marked = require('marked')
module.exports = source => {
    // console.log(source)
    // return 'console.log("hello~")'
    const html = marked(source)
    // return `moudle.exports = ${JSON.stringify(html)}`
    return `export default ${JSON.stringify(html)}`
}
 // 导出一个html
// (function(module, exports) {  module.exports = "export default"<h1 id=\"zxt\">ZXT</h1>\n"";/***/ })
// webpack.config.js
const path = require('path')

module.exports = {
  mode: 'none',
  entry: './src/main.js',
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist'),
    publicPath: 'dist/'
  },
  module: {
    rules: [
      {
        test: /.md$/,
        use: [
          'html-loader',
          './markdown-loader'
        ]
      }
    ]
  }
}
  • loader负责资源文件从输入到输出的转换
  • 对于同一个资源可以依次使用多个loader
7.webpack插件机制

loader专注实现资源模块加载

plugin解决项目中其他自动化工作(清除dist目录、拷贝静态文件到输出目录、压缩代码)

// 清除输出目录
// yarn add clean-webpack-plugin --dev
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
plugins: [
  new CleanWebpackPlugin()
]
// webpack 自动生成html插件   加babel插件会报错
// yarn   add html-webpack-plugin --dev
// 报错  npm i babel-loader @babel/core @babel/preset-env 
// yarn add html-webpack-plugin@3.2.0 --dev

plugins: [
    new CleanWebpackPlugin(),
    // 用于生成 index.html
    new HtmlWebpackPlugin({
        title: 'Webpack Plugin Sample',   // 设置标题
        meta: {
            viewport: 'width=device-width'
        },
        template: './index.html'  // 生成html的模板
    }),
    // 用于生成 about.html
    new HtmlWebpackPlugin({
        filename: 'about.html'
    })
]
// 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>Webpack</title>
</head>
<body>
  <div class="container">
    <h1><%= htmlWebpackPlugin.options.title %></h1>   // 传入的标题
  </div>
</body>
</html>
8.webpack常用插件
// npm i copy-webpack-plugin --dev  会报错
// npm i copy-webpack-plugin@5.0.4 --dev
const CopyWebpackPlugin = require('copy-webpack-plugin')
new CopyWebpackPlugin({
    // public/** public下的文件会拷贝到dist
    'public'
})

imagemin-webpack

9.webpack开发一个插件

插件通过在生命周期钩子函数中挂载函数实现扩展

// plugin通过钩子机制实现
// 必须是一个函数或是一个包含apply方法的对象
class MyPlugin {
  apply(compiler) {
    console.log('MyPlugin run')
    compiler.hooks.emit.tap('MyPlugin', compilation => {
      for (const name in compilation.assets) {
        // console.log(name)
        // console.log(compilation.assets[name].source())
        if (name.endsWith('.js')) {
          const contents = compilation.assets[name].source()
          // 替换代码中的注释
          const withoutComments = contents.replace(//**+*//g, '')
          // 覆盖原有内容
          compilation.assets[name] = {
            source: () => withoutComments,
            size: () => withoutComments.length
          }
        }
      }
    })
  }
}


new MyPlugin()
10.webpack实现监听
"scripts": {
    "build": "webpack --watch"
},
11.webpack自动刷新浏览器
// yarn add browser-sync --dev
// 启动 browser-sync dist --files "**/*"    和 webpack --watch
12.webpack dev server

集成[自动编译]和[自动刷新浏览器]等功能

打包的内容会自动存到内存中

// yarn add webpack-dev-server --dev
// yarn webpack-dev-server
// yarn webpack-dev-server --open  自动唤起浏览器
13.Webpack Dev Server静态资源访问
devServer: {
  contentBase: '/public'    // 额外为开发服务器指定查找资源目录
},
    
// const CopyWebpackPlugin = require('copy-webpack-plugin')  放在上线前使用
14.Webpack Dev Server 代理API

接口跨域

devServer: {
    contentBase: '/public',
    // http://localhost:8080/api/users   ---> https://api.github.com/api/users
    proxy: {
      '/api': {
        target: 'https://api.github.com',
        // http://localhost:8080/api/users   ---> https://api.github.com/users
        pathRewrite: {
          '^api': ''
        },
        // 不能使用 localhost:8080 作为请求 GitHub 的主机名
        changeOrigin: true
      },
    }
  },