初始化项目,安装webpack
mkdir my-projectcd my-projectnpm init -ynpm install webpack webpack-cli --save-dev
webpack.config.js配置
const path = require('path')
module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, mode: 'development' // production或none}
entry
// 单入口entry: './path/to/my/entry/file.js'
// 多入口entry: { app: './src/app.js', vendors: './src/vendors.js'}
output
output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist')}
// 多个入口起点,可使用[hash]、[chunkhash]、[name]、[id]、[query]filename: '[name].bundle.js',
loader
module: { rules: [ { test: /\.css$/, use: 'css-loader' }, { test: /\.ts$/, use: 'ts-loader' } ]}
plugins
常用的plugins
Name | Description |
---|---|
CommonsChunkPlugin | 将chunks相同的模块代码提取成公共js |
CleanWebpackPlugin | 清理构建目录 |
MiniCssExtractPlugin | 将CSS从bundle文件里提取成独立的CSS文件 |
CopyWebpackPlugin | 将文件或目录拷贝到构建目录 |
HtmlWebpackPlugin | 创建html文件以承载输出的bundle |
UglifyjsWebpackPlugin | 压缩js |
const HtmlWebpackPlugin = require('html-webpack-plugin')const webpack = require('webpack')plugins: [ new HtmlWebpackPlugin({template: './src/index.html'}), new webpack.optimize.UglifyJsPlugin()]
解析ES6
rules: [ { test: /\.js$/, use: 'babel-loader' }]
安装
npm i babel-loader @babel/core @babel/preset-env -D
配置
{ "presets": [ "@babel/preset-env" ]}
解析Less
rules: [ { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] }]
解析图片
rules: [ { test: /\.(png|jpg|jpeg|gif)$/, use: ['file-loader'] }]
可使用url-loader将小图片用base64引入。
文件监听
module.exports = { watch: true}
热更新
const webpack = require('webpack')module.exports = { plugins: [ new webpack.HotModuleReplacementPlugin() ], devServer: { contentBase: './dist', hot: true }, mode: 'development'}
命令
"scripts": { "dev": "webpack-dev-server --open"}
也可以使用webpack-dev-middleware实现热更新。
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)
app.use(webpackDevMiddleware(compiler, { publicPath: '/'}))
app.listen(3000, function () { console.log('Listening on port 3000');})
命令
"scripts": { "server": "node server.js"}
文件指纹
- hash: 和整个项目的构建相关,只要项目文件有修改,整个项目的hash值就会更改
- chunkhash: 和打包的chunk相关,不同entry会生成不同的chunkhash
- contenthash: 由文件内容生成
JS文件
output: { filename: '[name][chunkhash:8].js'}
CSS文件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = { plugins: [ new MiniCssExtractPlugin({ filename: '[name][contenthash:8].css', }) ], rules: [ { test: /\.less$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'less-loader' ] } ]}
图片、字体
// file-loader中的hash即为contenthashrules: [ { test: /\.(woff2?|eot|ttf|otf)$/, use: [ loader: 'file-loader', options: { name: '[name][hash:8].[ext]' } ] }]
代码压缩
JS文件
webpack4中已经内置并默认开启了uglifyjs-webpack-plugin,用于JS文件的压缩。
CSS文件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = { plugins: [ new MiniCssExtractPlugin({ filename: '[name][contenthash:8].css', }), new OptimizeCSSAssetsPlugin({ assetNameRegExp: /\.css$/g, cssProcessor: require('cssnano') }) ]}
HTML文件
通过设置html-webpack-plugin的压缩参数实现。
plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', filename: 'index.html', chunks: ['index'], minify: { collapseWhitespace: true, removeComments: true } })]
清理构建目录
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
// webpack's output.path directory will be removedplugins: [ new CleanWebpackPlugin()]
补齐CSS3前缀
安装
npm i postcss-loader autoprefixer -D
use: [ MiniCssExtractPlugin.loader, 'css-loader', 'less-loader', { loader: 'postcss-loader', options: { ident: 'postcss', plugins: [ require('autoprefixer')({ browsers: ['> 1%', 'last 2 versions', 'not ie <= 8'] }) ] } }]
px转换成rem
{ loader: 'px2rem-loader', options: { remUnit: 75, remPrecision: 8 }}
在html文件中添加根元素font-size自动计算方法。
资源内联
通过raw-loader内联HTML和JS。
<head> <title>INLINE</title> ${ require('raw-loader!./meta.html') } <script>${ require('raw-loader!babel-loader!./base.js') }</script></head>
使用style-loader或html-inline-css-webpack-plugin内联CSS文件。
多页面应用
利用glob动态获取entry并设置html-webpack-plugin。
const glob = require('glob')
const setMultipage = () => { const entry = {} const htmlWebpackPlugins = []
const entryFiles = glob.sync(path.resolve(__dirname, 'src/*/index.js')) entryFiles.forEach(entryFile => { const match = entryFile.match(/src\/(.*)\/index.js/) const pageName = match && match[1]
entry[pageName] = entryFile htmlWebpackPlugins.push( new HtmlWebpackPlugin({ template: `./src/${pageName}/index.html`, filename: `${pageName}.html`, chunks: [pageName] }) ) })
return { entry, htmlWebpackPlugins }}
const { entry, htmlWebpackPlugins } = setMultipage()
module.exports = { entry, plugins: [ new CleanWebpackPlugin() ].concat(htmlWebpackPlugins)}
待续 ~