Webpack 笔记

一、安装

1. 本地安装

# webpack 4+ 版本
npm install --save-dev webpack-cli
npm install --save-dev webpack

# 安装指定版本
npm install --save-dev webpack@<version>

2. 全局安装(官方不推荐)

npm install --global webpack

3. 最新体验版安装

npm install webpack@beta
npm install webpack/webpack#<tagname/branchname>

3. 运行

webpack

二、入门

1. 项目初始化

mkdir webpack-demo && cd webpack-demo

npm init -y

npm install webpack webpack-cli --save-dev

2. 初始化源码目录

mkdir src
cd src
new-item index.js
cd ..
mkdir dist
cd dist
new-item index.html

3. 创建配置文件 webpack.config.js

const path = require('path');

module.exports = {
  entry: './src/index.js', // 入口文件地址
  output: {
    filename: 'bundle.js', // 出口文件名
    path: path.resolve(__dirname, 'dist') // 告诉 webpack 在哪里生成文件
  }
};

4. 添加npm脚本

 {
    "name": "webpack-demo",
    "private": true,
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
+     "build": "webpack"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
      "webpack": "^4.0.1",
      "webpack-cli": "^2.0.9",
      "lodash": "^4.17.5"
    }
  }

5. 开始使用 webpack 打包:npm run build

具体事例请参考 example 目录下的 chapterOne

三、静态资源管理

0. 创建静态资源目录 asset

1. css

(1) 安装对应的 loader: npm install --save-dev style-loader css-loader

(2) 配置 loader:

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

(3) 静态资源目录添加 style.css 文件,在入口文件中引用,在打包时, webpack 会把对应的 css 代码插入到 index.html 的 head 中。

2. 图片

(1) 安装对应的 loader: npm install --save-dev file-loader

(2) 配置 loader:

{
  test: /\.(png|svg|jpg|gif)$/,
  use: [
    'file-loader'
  ]
}

(3) 静态资源目录添加一张图片,在入口文件中引用,打包时, webpack 会生成目标文件夹中的最终 url,并将入口文件中的路径替换为最终路径。

3. 字体

(1) 配置 loader:

{
  test: /\.(woff|woff2|eot|ttf|otf)$/,
  use: [
    'file-loader'
  ]
}

(2) 静态资源目录添加字体,在入口文件中引用,打包时, webpack 会生成目标文件夹中的最终 url,并将入口文件中的路径替换为最终路径。

4. 数据(json、xml、csv)

(1) 安装对应的 loader: npm install --save-dev csv-loader xml-loader

(2) 配置 loader:

{
  test: /\.(csv|tsv)$/,
  use: [
    'csv-loader'
  ]
},
{
  test: /\.xml$/,
  use: [
    'xml-loader'
  ]
}

(3) 静态资源目录添加对应的数据文件,在入口文件中引用数据文件, 打包之后,对应的数据文件会被处理为 json 格式的数据

具体事例请参考 example 目录下的 chapterTwo

四、输出管理

0. 入口分离

(1) 源码目录中新建 print.js 文件,并在 index.js 中引用对应模块,index.js 中引用对应的包

(2) webpack 配置修改:

const path = require('path');

module.exports = {
  mode: 'development',
  entry: {
    app: './src/index.js',
    print: './src/print.js'
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

1. 解决引用重复的问题,每次打包生成新的 html 文件

(1) 设定 HtmlWebpackPlugin

安装 html-webpack-plugin: npm install --save-dev html-webpack-plugin

(2) 配置 HtmlWebpackPlugin

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

plugins: [
  new HtmlWebpackPlugin({
    title: 'Output Management'
  })
],

(3) 在打包时, HtmlWebpackPlugin 会生成新的 index.html 文件,替换旧的 index.html 文件

2. 删除遗留的多余文件,在每次构建前清理 /dist 文件夹

(1) 安装插件: npm install clean-webpack-plugin --save-dev

(2) 配置插件:

const {
  CleanWebpackPlugin
} = require('clean-webpack-plugin');

new CleanWebpackPlugin(),

具体事例请参考 example 目录下的 chapterThree

五、开发环境配置

1. 将编译后的代码映射回原始源代码

(1) 配置文件中添加 source map 配置: devtool: 'inline-source-map'

(2) 入口文件有错误,控制台返回的错误路径是对应的源路径

2. 自动编译代码

(1) 观察模式:

  • 添加 script 脚本:"watch": "webpack --watch"

  • npm run watch,每次更新入口文件,代码将自动编译,但是每次编译后,需要手动刷新浏览器,页面才会更新

(2) webpack-dev-server(一个简单的web服务器,可以实时重新加载页面)(官方推荐使用)

  • 安装: npm install --save-dev webpack-dev-server

  • 修改配置文件:告知 webpack-dev-server 在哪里查找文件

devServer: {
  contentBase: './dist'
}
  • 添加 script 脚本
"start": "webpack-dev-server --open",
  • 修改源文件,web 服务器就会自动重新加载编译后的代码

(3) webpack-dev-middleware(模块热替换),把 webpack 处理后的文件传递给一个服务器(server)

  • 安装 express 和 webpack-dev-middleware: npm install --save-dev express webpack-dev-middleware

  • 配置文件中 output 添加 publicPat 选项: publicPath: '/'

  • 自定义一个 express 服务,添加 server.js 文件,内容如下:

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(webpackDevMiddleware(compiler, {
  publicPath: config.output.publicPath
}));

// Serve the files on port 3000.
app.listen(3000, function () {
  console.log('Example app listening on port 3000!\n');
});
  • 添加 npm script: "server": "node server.js",

  • 执行 npm run server, 打开 http://localhost:3000/ 即是项目地址

具体事例请参考 example 目录下的 chapterFour

六、模块热替换

1. 添加 webpack 自带的插件 NamedModulesPlugin 和 HotModuleReplacementPlugin

const webpack = require('webpack');

devServer: {
  contentBase: './dist',
  hot: true
},

plugins: [
  new webpack.NamedModulesPlugin(),
  new webpack.HotModuleReplacementPlugin()
],

2. 修改 index.js 文件,监听该文件所引用的外部文件的更新状况

if (module.hot) {
  module.hot.accept('./print.js', function() {
    console.log('Accepting the updated printMe module!');
    printMe();
  })
}

3. css 等静态资源加载了相应的 loader,会自动更新

4.其他热更新 loader 或插件

  • React Hot Loader:实时调整 react 组件。

  • Vue Loader:此 loader 支持用于 vue 组件的 HMR,提供开箱即用体验。

  • Elm Hot Loader:支持用于 Elm 程序语言的 HMR。

  • Redux HMR:无需 loader 或插件!只需对 main store 文件进行简单的修改。

  • Angular HMR:没有必要使用 loader!只需对主要的 NgModule 文件进行简单的修改,由 HMR API 完全控制。

七、输出优化

1. 移除 JavaScript 上下文中的未引用代码(dead-code)

package.json 文件设置 sideEffects 属性

"sideEffects": [
  "./src/some-side-effectful-file.js",
  "*.css"
]

2.压缩输出,设置编译模式为 production

mode: "production"

八、生产环境构建

1.构建目标比较

生产环境构建目标: 更小的 bundle、更轻量的 source map、更优化的资源、更短的加载时间

开发环境构建目标: 强大的 source map 和具有热模块替换能力的 localhost server

2.针对不同环境配置 webpack

(1) 安装 webpack-merge:npm install --save-dev webpack-merge

(2) 针对不同的环境创建对应的配置文件

// webpack.common.js
const path = require('path');
const {
  CleanWebpackPlugin
} = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: {
    app: './src/index.js'
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: 'Production'
    })
  ],
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [{
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          'file-loader'
        ]
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [
          'file-loader'
        ]
      },
      {
        test: /\.(csv|tsv)$/,
        use: [
          'csv-loader'
        ]
      },
      {
        test: /\.xml$/,
        use: [
          'xml-loader'
        ]
      }
    ]
  }
};
// webpack.dev.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack');

module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: {
    contentBase: './dist'
  },
  plugins: [
    new webpack.NamedModulesPlugin(),
    new webpack.HotModuleReplacementPlugin()
  ]
});
//webpack.prod.js
const merge = require('webpack-merge');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'production',
  plugins: [
    new UglifyJSPlugin({sourceMap: true}) // 不支持 es6 语法的压缩
  ]
});

(3) 修改 NPM Script

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

九、代码分离

1.针对多个文件指定对应的入口

2.把多个地方引用的代码分离到一个文件中,防止重复引用

optimization: {
  runtimeChunk: {
    name: "manifest"
  },
  splitChunks: {
    cacheGroups: {
      commons: {
        test: /[\\/]node_modules[\\/]/,
        name: "vendor",
        chunks: "all"
      }
    }
  }
}

3.动态导入

// output 添加 chunkFilename 字段
chunkFilename: '[name].bundle.js',
// index.js 动态引入库,编译之后可以看到对应的 loadash-chunk
async function getComponent() {
  var element = document.createElement('div');

  element.innerHTML = _.join(['Hello', 'webpack'], ' ');

  return element;
}
getComponent().then(component => {
  document.body.appendChild(component);
})

转载于:https://www.cnblogs.com/Canace22/p/11276803.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值