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')
}
複製代碼