skFeTeam 本文做者:李键css
做为一名前端开发,按时按质实现业务需求只是基础条件,了解一些webpack相关的配置,除了可以帮助咱们提高一下本身的技术能力(不局限于知足业务需求),也可以帮助咱们更好的维护项目、搭建适合本身团队的web站点。html
但愿经过本文能让你们对webpack4的相关配置项有一个直观的了解,以例子的形式帮助你们更好&更快的掌握相关知识点。前端
//webpack安装通常是不-g全局安装的,由于同时会进行好几个项目,有时候这几个项目的webpack版本都是不同的,所以都是根据项目来局部安装,只在独立的项目中有效。
npm install webpack-cli webpack --save-dev
//能够一路回车,初始化(项目名字,版本号,描述等默认就好,须要更改的能够在package.json文件中更改)
npm init/npm init -y
复制代码
//webpack打包的时候会默认找webpack.config.js文件
//使用path,首先须要引入
const path = require('path')
module.exports = {
mode: 'development',//开发模式
entry: './index.js',//指定入口文件
output: {
filename: 'bundle.js',//给成功打包的文件定义名字
path: path.resolve(__dirname,'dist'),//__dirname--相对webpack.config.js这个文件同级根目录,生成的打包文件dist目录下面
}
}
entry: {
main: './src/index',
sub: './src/index'
}
output: {
publicPath: ''---若是须要加域名的话能够这样配置
filename: '[name].js',---name占位符对应着entry中的key值
path: resolve.path(__dirname,'dist')
}
复制代码
npx webpack -v
npx webpack index.js
//在package.js的script能够配置运行打包命令
"script": {
"build": "webpack"
}
npm run build
复制代码
//webpack.config.js
module.exports = {
...
module: {
//规则数组类型--有不少不一样类型的打包规则
rules: [
{
test: /\.(jpg|png|jpeg)$/,
use: {
loader: 'file-loader',
options: {
//placehold--占位符 name--文件名,hash--hash值,ext-文件后缀名
name: '[name]_[hash].[ext]',
//回把图片打包到dist目录下image文件夹里
outputPath: "./image"
}
}
},{
test:/\.(eot|ttf|svg)$/,
use: {
loader: 'file-loader',
...
}
}
]
}
}
复制代码
rules: [
{
test:/\.(jpg|jepg|png)$/,
use: {
loader: 'url-loader',
options: {
filename: '[name]_[hash].[ext]',
outputPath: './image',
limit: 20480, //==20480个字节==20kb
//大于20kb就会打包成图片放在dist目录下面,小于则打包成base64字符串放在打包的js文件里面
}
}
}
]
复制代码
//使用file-loader ,url-loader 须要安装
npm install file-loader --save-dev
npm install url-loader --save-dev
复制代码
//安装loader
npm install style-loader css-loader sass-loader node-sass postcss-loader --save-dev
//在使用postcss-loader的时候须要借助插件
//autoprefixer
npm install autoprefixer -D
//使用postcss-loader还须要增长配置文件
//postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')
]
}
//webpack.config.js
module: {
rules: [
{
test: /\.css$/,
use: [
"style-loader",
<!--"css-loader",-->
{
loader: "css-loader",
options: {
//表示css文件中又引入css文件,这样配置项可使每一层均可以走到(下-上,右-左)
importLoader: 2,
//配置支持css模块化,避免样式渲染全局,name.类名的方式调用
<!--modules: true-->
}
}
"postcss-loader"
]
},{
test: /\.scss$/,
use:[
"style-loader",
<!--"css-loader",-->
{
loader: "css-loader",
options: {
importLoader: 2,
<!--modules: true-->
}
},
"sass-loader",
"postcss-loader"
]
}
]
}
复制代码
//首先安装html-webpack-plugin hlean-webpack-plugin
npm install html-webpack-plugin clean-webpack-plugin -D
//在webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new CleanWebpackPlugin('./dist')
]
}
复制代码
//因此引用这个插件必需要使用对象结构
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
//这个插件使用默认配置就行了,若是要传入参数的话,必须以对象的形式
new CleanWebpackPlugin()/ new CleanWebpackPlugin({})
复制代码
//webpack.config.js
module.exports = {
//基本配置
devtool: "source-map"
//能够提示比较全面的错误信息,具体到哪一行哪一列第几个字符,而且映射文件会打包到打包文件里面
devtool: "inline-source-map"
//开发环境配置推荐
devtool: "cheap-module-eval-source-map"
//生产环境
devtool: "cheap-module-source-map"
}
复制代码
//先安装webpack-dev-server
npm install webpack-dev-server -D
//package.json
"scripts": {
"watch": "webpack --watch",
"start": "webpack-dev-server",
}
//webpack.config.js
devServer: {
contentBase: './dist',//本地服务器加载的目录
open: true,//打包完成以后自动帮咱们启动一个本地服务器,端口默认是8080,
port: "",//端口能够自定义
...
}
复制代码
// weebpack.config.js
const webpack = require('webpack');
module.exports = {
devServer: {
contentBase: './dist',
port: 8080,
open: true,
hot: true,//--开启热更新功能
hotOnly: true,//阻止页面自动刷新,即便hot更新功能不起做用,浏览器也不自动刷新页面
}
plugins: [
new webpack.HotModuleReplacementPlugin()
]
}
//js
if(module.hot) {
module.hot.accept('./number',() => {
document.body.removeChild(document.getElementById('id'))
number()//从新执行一下这个模块的函数
})
}
复制代码
//安装插件 --@babel/core是babel核心库
npm install babel-loader @babel/core -D
//同时要按装,babel-loader只是打通webpack的一个桥梁,并不会转义代码,须要借助@babel/preset-env 来作语法的转换
npm install @babel/preset-env -D
//还有继续安装@babel/polyfill -- 做用是帮助低版本的浏览器弥补缺失的变量以及函数,同时能够在options配置,根据业务代码来作低版本的缺失弥补,这样打包代码能够作到精简,注意的是,这个插件只适合作业务代码带包,由于会污染全局
npm install @babel/polyfill -D
//新建.babelrc文件,options配置能够放在这个文件里面
{
presets: [
[
"@babel/preset-env",
{
"targets": {
"chrome": "67"
},
"useBuiltIns": "usage"// 按需加载
}
]
]
}
//webpack.config.js
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
<!--options: {-->
<!-- presets: [['@babel/preset-env',{targets: {chrome: "67",},useBuiltIns: 'usage'}]]--> <!--}--> //test code --es6 import '@babel/polyfill' const arr = [ new Promise(() => {}), new Promise(() => {}) ] arr.map(item => { console.log(item) }) 复制代码
//使用安装插件
npm install react react-dom --save-dev
npm install @babel/preset-react --save-dev
//.babelrc中去引用插件
presets:[
"@babel/preset-react"
]
//js--test-code
import React ,{ Component } from 'react'
import ReactDom from 'react-dom'
class App extends Compnent {
render() {
return(<div>herllo world</div>)
}
}
ReactDom.render(<App/>,document.getElementById('root'));
复制代码
//webpack.config.js
module.exports = {
plugins: [],
optimization: {
usedExports:true//只是在开发环境须要配置,在生产环境把不须要配置
}
}
//package.json中 开发环境是会保留这段代码的
"sideEffects": ['*.css']---忽略相关模块不作tree shaking
复制代码
//须要下载 webpack-merge
npm install webpack-merge -D
//dev
const webpack = require('webpack');
const devConfig = {
mode: 'development',
devtool: 'cheap-module-source-map',
devServer: {
contentBase: '../dist',//本地服务器加载的目录
open: true, //打包完成以后自动打开浏览器
// port: 8080,
hot: true,//开启模块热更新更能
hotOnly: true,//阻止页面刷新,即便热更新功能失效,也不会刷新页面
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
optimization: {
usedExports:true,
},
}
module.exports = devConfig;
//pord
const pordConfig = {
mode: 'production',//production
}
module.exports = pordConfig;
//common
const path = require('path');
const merge = require('webpack-merge')
const devConfig = require('./webpack.dev.js');
const prodConfig = require('./webpack.prod.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const commonConfig = {
entry: {
main: './src/index.js'
},
module: {
//规则数组类型--有不少不一样类型的打包规则
rules: [
// {
// test: /\.(jpg|png|jpeg)$/,
// use: {
// loader: 'file-loader',
// options: {
// //placehold--占位符 name--文件名,hash--hash值,ext-文件后缀名
// name: '[name]_[hash].[ext]',
// //回把图片打包到dist目录下image文件夹里
// outputPath: "./image"
// }
// }
// },
{
test: /\.js$/,
exclude:/node_modules/,
loader: 'babel-loader'
},
{
test: /\.(jpg|png|jpeg)$/,
use: {
loader: 'url-loader',
options: {
//placehold--占位符 name--文件名,hash--hash值,ext-文件后缀名
name: '[name]_[hash].[ext]',
//回把图片打包到dist目录下image文件夹里
outputPath: "./image",
limit: 204800,
},
}
},{
test:/\.(eot|ttf|svg)$/,
use: {
loader: 'file-loader',
}
},{
test: /\.css$/,
use: [
"style-loader",
"css-loader",
"postcss-loader"
]
},{
test: /\.scss$/,
use: [
"style-loader",
"css-loader",
"sass-loader",
"postcss-loader"
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
// * All files inside webpack's output.path directory will be removed once, but the
// * directory itself will not be. If using webpack 4+'s default configuration,
// * everything under <PROJECT_DIR>/dist/ will be removed.
new CleanWebpackPlugin({ verbose: true,cleanOnceBeforeBuildPatterns:['**/*']}),
],
output: {
filename: 'bundle.js',//打包成功后的文件名
path: path.resolve(__dirname,'../dist'),//__dirname---表示跟web.config.js的同级根目录,打包以后的文件夹
}
}
module.exports = (env) => {
if(env&&env.production) {
return merge(commonConfig,prodConfig)
}else{
return merge(commonConfig, devConfig)
}
}
//package.js
"script": {
"start": "webpack-dev-server --config ./build/webpack.common.js",
"build": "webpack --env.production --config ./build/webpack.common.js",
"dev": "webpack --env.development --config ./build/webpack.common.js"
}
复制代码
//异步代码分割,安装babel插件,babel-plugin-dynamic-import-webpack
npm install babel-plugin-dynamic-import-webpack -D
//同步代码分割的话须要在optimization中配置splitChunks
//---在.babelrc中去配置一个plugins,
presets: [],
plugins: ["dynamic-import-webpack"]
//webpack.common.js
optimization: {
splitChunks: {
chunks: 'all'//对同步代码和异步代码同时作代码分割
chunks:'aysnc'//对异步代码作分割
}
}
//test-code--index.js
function getComponent() {
return import('lodash').then(({default:_}) => {
var element = document.createElement('div');
element.innerHTML = _.join(['dell','lee'],'_');
return element
})
}
getComponent().then(element => {
document.body.appendChild(element);
})
复制代码
npm install @babel/plugin-syntax-dynamic-import --save-dev
splitChunks: {
chunks: async //--若是是async的话,只是对异步代码作代码分割,all是对异步和同步分都作代码分割
minSize: 30000===30kb //大于30kb就会作代码分割,小于的话就作代码分割
maxSize:0,//可配可不配 --若是是50000===50kb, 会作二次分割 lodash 打包成1mb ,会拆成20个50kb代码分割
minChunks: 1,//当这个模块使用几回的话在作代码分割,小于的设置的次数就不作代码分割
maxAsyncRequests: 5,//同时加载的模块是5个,在打包前五个会帮你打包作代码分割,超过五个的话就不作代码分割
maxInitialRequests: 3,//指整个网站首页进行加载的时候或者是入口文件进行加载的时候,入口文件会引入其余库,也只能最多三个,超过三个就不会作代码分割了
automaticNameDelimiter: '~',//文件生成的时候,文件的中间会有一些链接符,
name: true, ---//起什么名字,让cacheGroups中的名字有效
cacheGroups: {//若是是同步的话会走完chunks以后会走这个配置,缓存组
vendors: {
test: /[\\/]node_modules[\\/]/,//--是同步代码发现是从node_modules引入的话,那么符合这个组会被打包成单独文件
priority: -10
filename: 'vendors.js'//是打包文件的名字
}
default: {
priority: -20,//假设同时符合两个组,经过这个配置来设置优先级,值越大,优先级越高
reuseExistingChunk: true,若是一个模块a,b,若是a使用了b,符合代码分割的要求,而后又符合default这个组,就不打包以前打包过的内容
filename: 'common.js'
}
}
}
复制代码
//安装插件
npm install mini-css-extract-plugin --save-dev
//线上环境单独生成的css文件须要作代码压缩合并
npm install optimize-css-assets-webpack-plugin -D
//optimization
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require(' optimize-css-assets-webpack-plugin')
//配置作更改
//开发环境使用规则默认
//线上环境
module: {
rules: [
use: ['MiniCssExtractPlugin.loader'] //全部使用style-loader所有替换,不使用style-loader
]
},
optimization: {minimizer: [new OptimizeCssAssetsWebpackPlugin({})]},
plugins: [new MiniCssExtractPlugin({
filename: '[name].css',//被文件直接引用走这个配置
chunkFilename: '[name].chunk.css'//被间接引用的话是走这个配置项
})]
output: {
filename: '[name].js',
chunkFilename: '[name].chunk.js',//就是被js间接引用的打包文件就会走这个配置内容,
path: path.resolve(__dirname,'../dist')
}
复制代码