从零配置简单Webpack
一、安装
npm init -y
npm install webpack webpack-cli --save-dev
注意:npm初始化后的 package.json 里的 name 属性不能与 webpack 同名。
二、创建配置文件
一般有两种方法:
- 基础配置文件 + 开发环境配置文件 + 生产环境配置文件
- 开发环境配置文件 + 生产环境配置文件
这里用第二种:根目录下创建 webpack.dev.js 和 webpack.prod.js 两个文件。
然后在 package.json 里添加两个脚本:
"build": "webpack --config webpack.prod.js",
"dev": "webpack-dev-server --config webpack.dev.js"
三、安装常用loader和plugin
安装:
npm install webpack-dev-server --save-dev
npm install html-webpack-plugin --save-dev
npm install css-loader --save-dev
npm install style-loader --save-dev
npm install sass-loader node-sass --save-dev
npm install clean-webpack-plugin --save-dev
npm install @babel/core @babel/preset-env babel-loader --save-dev
npm install file-loader --save-dev
npm install url-loader --save-dev
npm install html-loader --save-dev
npm install mini-css-extract-plugin --save-dev
npm install postcss-preset-env postcss-loader --save-dev
npm install optimize-css-assets-webpack-plugin --save-dev
npm install @babel/polyfill --save-dev
npm install core-js --save-dev
作用:
- webpack-dev-server:开启调试的服务器。
- html-webpack-plugin:处理html。
- css-loader:处理css文件。
- style-loader:将处理好的css代码引入到style标签内。
- sass-loader node-sass:处理sass。
- clean-webpack-plugin:在重新生成打包文件夹前将dist文件夹删除。
- @babel/core @babel/preset-env babel-loader:大部分 es6–>es5,promise 等无法转换。
- file-loader:处理各类资源文件(字体图标、视频等)。
- url-loader:处理(图片)路径。
- html-loader:处理html内的img标签。
- mini-css-extract-plugin:将css代码从bundle.js中分离成单个文件。
- postcss-preset-env postcss-loader:前者处理css最新语法的兼容性问题,自动加浏览器内核前缀,注意在package.json配置browserslist;后者是处理css的工具集,看具体配置了什么。
- optimize-css-assets-webpack-plugin:压缩css。
- @babel/polyfill:谨慎引入polyfill,会导致打包后的js文件变巨大,用法是在入口文件引入import ‘@babel/polyfill’,配置文件无需更改。
- core-js:按需处理js兼容性问题,就不再需要 @babel/polyfill 了。
四、附录
// package.json
"browserslist":{
"development":[
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
"production":[
">0.2%",
"not dead",
"not op_mini all"
]
}
// 测试browserlist里的开发环境,需要给Node.js定环境变量,
// 而不是修改webpack的开发模式(默认为生产环境)。
// webpack.dev.js
process.env.NODE_ENV = 'development'
// webpack.dev.js
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = {
mode: 'development',
entry: resolve(__dirname, 'src', 'index.js'),
output: {
filename: 'bundle.js',
path: resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
ident: 'postcss', // webpack要求要给的唯一标识
plugins:()=>[
require('postcss-preset-env')()
]
}
}
]
},
{
test: /\.scss$/,
use: [{
loader: MiniCssExtractPlugin.loader // 将 JS 字符串生成为 style 节点
}, {
loader: "css-loader" // 将 CSS 转化成 CommonJS 模块
}, {
loader: "sass-loader" // 将 Sass 编译成 CSS
}]
},
{
test: /\.js$/,
loader: ['babel-loader'],
include: resolve(__dirname, 'src'),
exclude: /node_modules/,
options:{
presets:[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
// 指定core-js版本
corejs:{
version: 3
},
// 指定兼容性做到哪个版本浏览器
target:{
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]
}
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[hash:5].[ext]',
limit: 8192,
// 默认情况下url-loader用es6的方法引入,跟html-loader配合时会出错,所以要设置为false
esModule: false
}
}
]
},
{
test: /\.(html)$/,
use: {
loader: 'html-loader'
}
},
{
test: /\.(eot|svg|woff|woff2|ttf|mp3|mp4|avi)$/,
// 或者排除html/css/js/scss等其他处理过的
// exclude: /\.(html|css|js|scss)$/,
loader: ' file-loader',
options: {
name: '[hash:5].[ext]'
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
// 模板
template: resolve(__dirname, 'src', 'index.html'),
// 输出文件名
filename: 'index.html'
}),
// 使用MiniCssExtractPlugin就要把所有style-loader换成MiniCssExtractPlugin.loader
new MiniCssExtractPlugin({
// filename: 'css/main.css'
}),
new OptimizeCssAssetsPlugin()
],
devServer: {
port: 3000,
contentBase: resolve(__dirname, 'dist'),
open: true,
compress: true,
hot: true
},
// 方便调试
devtool: 'cheap-module-eval-source-map'
}
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = {
mode: 'production',
entry: resolve(__dirname, 'src', 'index.js'),
output: {
filename: 'bundle.js',
path: resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
ident: 'postcss', // webpack要求要给的唯一标识
plugins:()=>[
require('postcss-preset-env')()
]
}
}
]
},
{
test: /\.scss$/,
use: [{
loader: MiniCssExtractPlugin.loader // 将 JS 字符串生成为 style 节点
}, {
loader: "css-loader" // 将 CSS 转化成 CommonJS 模块
}, {
loader: "sass-loader" // 将 Sass 编译成 CSS
}]
},
{
test: /\.js$/,
loader: ['babel-loader'],
include: resolve(__dirname, 'src'),
exclude: /node_modules/,
options:{
presets:[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
// 指定core-js版本
corejs:{
version: 3
},
// 指定兼容性做到哪个版本浏览器
target:{
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]
}
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[hash:5].[ext]',
limit: 8192,
// 默认情况下url-loader用es6的方法引入,跟html-loader配合时会出错,所以要设置为false
esModule: false
}
}
]
},
{
test: /\.(html)$/,
use: {
loader: 'html-loader'
}
},
{
test: /\.(eot|svg|woff|woff2|ttf|mp3|mp4|avi)$/,
// 或者排除html/css/js/scss等其他处理过的
// exclude: /\.(html|css|js|scss)$/,
loader: ' file-loader',
options: {
name: '[hash:5].[ext]'
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
// 模板
template: resolve(__dirname, 'src', 'index.html'),
// 输出文件名
filename: 'index.html',
// 压缩HTML
minify:{
collapseWhitespace: true,
removeComments: true
}
}),
// 使用MiniCssExtractPlugin就要把所有style-loader换成MiniCssExtractPlugin.loader
new MiniCssExtractPlugin({
// filename: 'css/main.css'
}),
new OptimizeCssAssetsPlugin()
],
// 分割代码,像vue的脚手架生成的js文件一样有多个,也即多个chunk。并且会分析有无相同的文件。
optimization: {
splitChunks: {
chunks: 'all'
}
}
}
开发环境和生产环境的配置,按实际情况更改。
例如配置eslint,上面无配置,一般ide就能实现,这里仅作补充。
npm install eslint-config-airbnb-base eslint-plugin-import eslint --save-dev
// webpack配置文件
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
options: {
fix: true
}
}
// package.json
"eslintConfig": {
"extends": "airbnb-base"
}
五、参考
https://juejin.im/post/5b4609f5e51d4519596b66a7
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!