"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --config ./config/webpack.dev.js",
"build": "webpack --config ./config/webpack.pro.js"
},
"devDependencies": {
"@babel/core": "^7.7.7",
"@babel/plugin-transform-runtime": "^7.7.6",
"@babel/preset-env": "^7.7.7",
"@babel/runtime": "^7.7.7",
"autoprefixer": "^9.7.3",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.0",
"file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0",
"less": "^3.10.3",
"less-loader": "^5.0.0",
"mini-css-extract-plugin": "^0.9.0",
"postcss-loader": "^3.0.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",
"webpack-merge": "^4.2.2"
},
"dependencies": {
"@babel/polyfill": "^7.7.0"
}
// webpack.base.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
entry: {
index: './src/js/index.js'
},
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].js'
},
module: {
rules: [
{
test: /\.(jpe?g|png|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048,
}
}
},
{
test: /.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
// {
// targets: {
// edge: '17',
// firefox: '60',
// chrome: '67',
// safari: '11.1'
// },
// useBuiltIns: 'usage', // 按需加载
// // 会污染全局环境, 开发组件库的话 推荐闭包方式 @babel/plugin-transform-runtime
// }
]
],
plugins: ['@babel/plugin-transform-runtime']
}
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: '首页',
template: './src/pages/index.html',
inject: true,
chunks: ['index'],
filename: 'index.html'
}),
new CleanWebpackPlugin(),
]
}
// webpack.dev.js
const webpack = require('webpack')
const merge = require('webpack-merge')
const baseConfig = require('./webpack.base')
const devConfig = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
devServer: {
port: 8081,
open: true,
hotOnly: true, // 即使 HMR不生效,不自动刷新
},
module: {
rules: [{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader', {
loader: 'postcss-loader',
options: {
plugins: () => [
require('autoprefixer')({
overrideBrowserslist: ['last 2 versions', '>1%']
})
]
}
}]
}, ]
},
plugins: [
new webpack.HotModuleReplacementPlugin() // 模板化更新
]
}
module.exports = merge(baseConfig, devConfig)
// webpack.pro.js
const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const merge = require('webpack-merge')
const baseConfig = require('./webpack.base')
const proConfig = {
mode: 'production',
output: { // 输出文件
path: path.resolve(__dirname, '../dist'),
filename: '[name]_[chunkhash:8].js'
},
devtool: 'none', // 线上推荐不开启
module: {
rules: [{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader', {
loader: 'postcss-loader',
options: {
plugins: () => [
require('autoprefixer')({
overrideBrowserslist: ['last 2 versions', '>1%']
})
]
}
}]
}, ]
},
plugins: [
new MiniCssExtractPlugin({ // css 分离成文件
filename: "[name]_[contenthash:8].css"
}),
]
}
module.exports = merge(baseConfig, proConfig)
在改变 number.js 中的值时, 只有此处会刷新.
// index.js
import number from './number'
number()
if(module.hot) {
module.hot.accept('./number', function() {
document.body.removeChild(document.getElementById('number'))
number()
})
}
// number.js
function number() {
var div = document.createElement('div')
div.setAttribute('id', 'number')
div.innerHTML = 100
document.body.appendChild(div)
}
export default number;
如果只想统一配置的话请查看上一篇: webpack的简单配置