一、全局安装nodejs
安装后检验:cmd中:node -v,出现版本号即安装成功。
二、安装webpack
1.新建项目文件夹item,cmd中进入项目:cd item
2.初始化:cmd中:npm init -y,生成package.json文件
3.安装webpack和webpack-cli:cmd中:npm install --save-dev webpack webpack-cli
4.项目文件夹中添加src文件夹,src 文件夹中添加 index.js: document.write(111);(默认入口文件文件src/index.js)
5.项目文件夹中添加dist文件夹,dist文件夹中添加index.html: <script src="main.js"></script>(默认输出文件文件dist/main.js)
6.编译:cmd中:npx webpack ,自动生成main.js
三、使用配置文件
1.项目文件夹中创建webpack.config.js:(默认配置文件webpack.config.js)
作用:更改输入输出文件等
const path = require('path');
module.exports = {
mode: 'development', //模式:production(默认) 、development
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
.编译:cmd中: npx webpack, 自动生成dist/bundle.js
2.若想修改webpack.config.js文件名,则在cmd中: npx webpack --config 新的文件名
3.若新文件名太长,则在package.json中做配置:
"scripts": {
"build": "webpack --config 新文件名"
},
编译:cmd中: npm run build, 自动生成dist/bundle.js
四、挂载到本地服务器
1.安装webpack-dev-server:
npm i webpack-dev-server --save-dev
2.package.json中:
"scripts": {
"dev": "webpack-dev-server"
},
3.webpack/config.js中设置devServer配置服务器:
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
devServer: { // 开发服务器的配置
host: 'localhost',
port: 3000, // 端口
progress: true, // 打包时进度条
contentBase: './dist', // 浏览器打开时默认路径
compress: true //启用gzip压缩
}
}
4.生成:
npm run dev
浏览器打开localhost:3000
五、自动生成html,并载入打包好的文件
1、安装html-webpack-plugin:
npm i --save-dev html-webpack-plugin
2.在webpack.config.js中配置:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
.........
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', //模板文件
filename: 'index.html', //生成的文件名
minify: { //压缩输出,mode为production时为true ,否则为false
removeAttributeQuotes: true, // 删除双引号
collapseWhitespace: true // 变为一行
},
hash: true, // 打包时的js文件在引用时带上?hash,如src=bundle.js?8ae46c61ad7a73e29468
})
]
}
3.npm run build,自动生成dist/index.html
六、生成内联样式
1.css-loader:解析@import语法。
style-loader: 把css插入head标签中。
loader特点:功能单一;一个loader用字符串,多个loader 用数组;执行顺序为从右到左。
2.安装: npm i --save-dev css-loader style-loader
3.webpack.config.js中配置:
module.exports = {
。。。。。。
module: {
rules:[
//loader执行顺序为从右到左,先解析css再插入head标签中,所以style-loader需放在css-loader左边
{ test: /\.css$/,use:[
{
loader: 'style-loader'
},
'css-loader'
]},
{
test: /\.scss$/,
use: [
{
loader: 'style-loader'
},
'css-loader',
'sass-loader' //解析scss需安装node-sass,但不需要写入
]
}
]
}
}
4.生成:npm run dev ,生成内联样式<style>....</style>
七、生成外联样式
1.安装:npm i mini-css-extract-plugin --save-dev
2.webpack.config.js中配置:
。。。。
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
。。。。
plugins: [
。。。。
new MiniCssExtractPlugin({
filename: 'main.css'
})
],
module: {
rules:[
{ test: /\.css$/,use:[
// {
// loader: 'style-loader'
// },
// 将style-loader替换成MiniCssExtractPlugin(css插入head标签替换成外联的css)
MiniCssExtractPlugin.loader,
'css-loader'
]},
{
test: /\.scss$/,
use: [
// 'style-loader',
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
}
]
}
}
3.生成: npm run build ,生成
八、压缩css、js
1.安装插件:
cnpm i --save-dev optimize-css-assets-webpack-plugin //压缩css
cnpm i --save-dev uglifyjs-webpack-plugin //压缩js
2.webpack.config.js中配置:
。。。。
const OptimizeCss= require('optimize-css-assets-webpack-plugin'); //压缩css
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
。。。。
plugins: [
。。。。
new UglifyJsPlugin({ //压缩js
cache: true, //使用缓存
parallel: true, // 并行打包
sourceMap: true
}),
new OptimizeCss() //压缩css
],
。。。。
}
3.打包: npm run build 生成压缩好的文件
九、将ES6转化为ES5
1.安装: babel-loader,@babel/core, @babel/preset-env, @babel/plugin-proposal-class-properties
cnpm i babel-loader @babel/core @babel/preset-env --save-dev
cnpm i @babel/plugin-proposal-class-properties --save-dev // 解析class
cnpm i @babel/plugin-proposal-decorators --save-dev //解析装饰器
2.webpack.config.js中配置:
。。。。。
module.exports = {
。。。。
module: {
rules: [
。。。。。
{
test: /\.js$/,
use: {
loader: 'babel-loader', // 将RS6转为ES5
options: {
presets: ['@babel/preset-env'],
plugins:[
// '@babel/plugin-proposal-class-properties', // 解析class
['@babel/plugin-proposal-decorators', { //解析装饰器
'legacy': true
}],
['@babel/plugin-proposal-class-properties', { "loose" : true}] // 解析class
]
}
}
}
]
}
}
十、优化
1.安装:
cnpm i --save @babel/plugin-transform-runtime //解析高级语法(generator、promise)并优化
cnpm i --save @babel-runtime
cnpm i --save @babel-polyfill //解析更高级语法(includes())
2.在webpack.config.js中配置:
。。。。
module.exports = {
。。。。。。。
module: {
rules: [
。。。。。
{
。。。。
use: {
。。。。。。
options: {
。。。。。。
plugins:[
。。。。
"@babel/plugin-transform-runtime" //解析高级语法(generator、promise)并优化
]
}
}
}
]
},
}
3.在src/index.js中
require('@babel/polyfill');
十一、校验
1.安装:
cnpm i --save-dev eslint eslint-loader
2.webpack.congfig.js中配置:
。。。。
module.exports = {
。。。。
module: {
rules: [
。。。。。
{
test: /\.js$/,
use: {
loader: 'eslint-loader',
options: {
enforce: 'pre' //强制在其他loader之前执行
}
},
}
]
},
}
3.在eslint官网勾选并下载规则包.eslintrc.json
十二、设置全局变量
1.以jquery为例,安装jquery
2.设置为全局变量:
方法一:
在src/index.js中使用expose-loader:z window上挂载$
// import $ from 'jquery';
require('expose-loader?$!jquery')
console.log($);
console.log(window.$);
方法二:
webpack.congfig.js中使用expose-loader:
。。。。。
module.exports = {
。。。。。。。
module: {
rules: [
。。。。
{
test: require.resolve('jquery'), //请求jquery时
use: 'expose-loader?$!jquery'
}
]
},
}
方法三:
webpack.congfig.js中使用webpack.ProvidePlugin:在每个模块中挂载$
。。。。。
const webpack = require('webpack');
module.exports = {
。。。。。
plugins: [
。。。。。。
new webpack.ProvidePlugin({
$: 'jquery'
})
]
}
方法四:直接用script标签引入cdn,但为了避免文件中引入的jq重复打包,在webpack.congfig.js中使用externals:
。。。。
module.exports = {
。。。。
externals: { //不打包
jquery: 'jQuery'
},
。。。。
}
十三、图片处理
1. 通过js和css载入的图片用file-loader,安装file-loader
webpack.config.js中配置file-loader:
。。。。
module.exports = {
。。。。。
module: {
rules: [
{
test: /\.(jpg|png|gif)$/,
use: 'file-loader'
},
。。。。。。
]
}
}
通过js载入的在src/index.js中:
import logo from './index.png'
let img = new Image();
img.src = logo; // 不能直接写字符串,解析不了
console.log(img.src);
document.body.appendChild(img);
2.通过html载入的图片用html-withimg-loader
安装html-withimg-loader
webpack.config.js中配置file-loader:
。。。。
module.exports = {
。。。。。
module: {
rules: [
{
test: /\.html$/,
use: 'html-withimg-loader'
},
。。。。。。
]
}
}
在index.html中引入图片:
<img src="index.png">
3.小图片转为base64:
安装url-loader
webpack.config.js中配置url-loader:
。。。。
module.exports = {
。。。。。
module: {
rules: [
{
test: /\.(jpg|png|gif)$/,
// 当图片小于多少K时,用url-loader转化成base64
// 否则用file-loader产生真实图片
// use: ['file-loader']
use:{
loader: 'url-loader',
options:{
limit: 5 * 1024, //小于5k的图片转化为base64
outputPath:'img/' //大于5k的图片生成在img目录下
}
}
},
。。。。。。
]
}
}
十四、报错定位
1.安装source-map:
npm i --save-dev source-map
2.在webpack.config.js中配置:
。。。。
module.exports = {
。。。。
devtool: 'source-map', // 定位到源码位置,并生成源码独立文件
// devtool: 'eval-source-map', //安装时404
// devtool: 'cheap-module-source-map', //安装时404
// devtool: 'cheap-module-eval-source-map', //安装时404
}
3.npm run dev ,生成源码独立文件,报错时定位到源码列
十五、实时打包
在webpack.config.js中配置:
。。。。
module.exports = {
。。。。
watch: true,
watchOptions: {
poll: 1000, //1秒检测1000次
aggregateTimeout: 500, //防抖:输入500毫秒后再执行
ignored: /node_modules/ //不需要监控的文件
},
}
十六、清除文件夹
1.安装 clean-webpack-plugin
2.在webpack.config.js中配置:
。。。。
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
。。。。
plugin: [
new CleanWebpackPlugin() //默认删除output.path
]
}
十七、拷贝文件
1.安装copy-webpack-plugin
2.在webpack.config.js中配置:
。。。。
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
。。。。
plugin: [
new CopyWebpackPlugin([
{from: 'doc', to:'./'} //doc目录下的文件拷贝到当前目录下(dist)
])
]
}
十八、添加版权标识
在webpack.config.js中配置:
。。。。
const webpack = require('webpack');
module.exports = {
。。。。
plugin: [
new webpack.BannerPlugin('make 2019 by jwy') //版权标识会被注释到打包文件最前
]
}
十九、处理跨域
1.代理:
在webpack.config.js中配置:
。。。。
module.exports = {
。。。。
devServer: {
proxy:{ //跨域代理
'/api': { //所有接口共有
target: 'http://localhost:3000', //指向域名
pathRewrite:{'^/api': ''} // 将/api改为空字符串
}
}
}
}
在src/index.js中发起请求:
var xhr = new XMLHttpRequest();
xhr.open('GET','/api/user', true);
xhr.onload = function() {
console.log(xhr.response);
}
xhr.send();
创建服务器server.js:
let express = require('express');
let app = express();
app.get('/api/user', (req, res)=> {
res.json({name:'jwy'})
})
console.log(122);
app.listen(3000)
2.webpack中模拟接口,不用服务器
在webpack.config.js中配置:
。。。。
module.exports = {
。。。。
devServer: {
before(app) {
app.get('/api/user', (req, res) => { //模拟接口
res.json({name: 'jqwy'})
})
}
}
}
3.在服务端中启用webpack,端口使用服务端端口:
在服务器server.js中配置处理webpack和中间件webpack-dev-middleware:
let express = require('express');
let app = express();
let webpack = require('webpack');
let middle = require('webpack-dev-middleware'); //中间件
let config = require('./webpack.config.js'); //引入webpack配置文件
let compiler = webpack(config); //用webpack处理config文件,并返回编译后结果
app.use(middle(compiler)); //app中使用中间件
app.get('/api/user', (req, res)=> {
res.json({name:'j222wy'})
})
console.log(122);
app.listen(3000)
在localhost:3000/api/user 中可以访问到/api/user接口
在localhost:3000/index.html 中可以访问到src/index.html
二十、解析第三方包
1. 在webpack.config.js中配置:
。。。。
module.exports = {
。。。。
resolve: { //解析第三方包
modules: [path.resolve('node_module')], // 只在node_module文件夹中找包
extensions: ['.js', '.css', '.json', '.vue'], //解析引入的没有后缀名的文件
mainFields: ['style', 'main'], // 先查找package.json中的style对应的路径,若无再查找main(默认是查找main)
mainFiles: [], //入口文件名(默认index.js)
alias: { //设置别名
bootstrap: 'bootstrap/dist/css/bootstrap.css'
}
}
}
二十一、定义编译时全局常量
1. 在webpack.config.js中配置:
。。。。
module.exports = {
。。。。
plugins: [
new webpack.DefinePlugin({ //创建一个在编译时可以配置的全局常量(引号里是表达式,字符串需用JSON.stringify())
DEV: JSON.stringify('dev'), //相当于 var DEV='dev'
BOOL: 'true', //相当于var BOOL = true
EXPRESS: '1+2' // 相当于var EXPRESS = 1+2
})
]
}
在src/index.js中:
let url = '';
if(DEV === 'dev') {
url = 'localhost: 8080';
} else {
url = 'http://juntao.com';
}
console.log(url);
二十二、区分不同环境
1.安装webpack.merge
2.将webpack.config.js改为webpack.base.js
3.新建webp.dev.js和webpack.prod.js:
const {smart} = require('webpack-merge');
let base = require('./webpack.base.js');
module.exports = smart(base, {
mode: 'development',
devServer: {
}
})
const {smart} = require('webpack-merge');
let base = require('./webpack.base.js');
module.exports = smart(base, {
mode: 'production',
})
二十三、不解析文件依赖库(优化)
1. 在webpack.config.js中配置:
。。。。
module.exports = {
。。。。
module: {
noParse: /jquery | loader/ // 不去解析这些文件的依赖库(当这些文件无依赖库时可这样设置)
}
}
二十四、忽视插件中引入配置的代码
1. 在webpack.config.js中配置:
。。。。
module.exports = {
。。。。
plugins:[
new webpack.IgnorePlugin(/\.\/locale/, /moment/) //moment插件中如果使用./locale引入配置,则忽略
]
}
二十五、动态链接库(第三方库过大,打包起来耗时间时可用)
以react、react-DOM为例:
1.安装react、react-dom、babel-loader、@babel/core、@babel/preset-env、@babel/preset-react
2.创建webpack.react.js:
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: 'development',
entry: {
react: ['react', 'react-dom']
},
output: {
filename: '__dll__[name].js',
path: path.resolve(__dirname, 'dist'),
library: '__dll__[name]', //为打包输出的东西设置变量名
libraryTarget: 'var' //声明变量的关键字(默认var)
},
plugins: [
new webpack.DllPlugin({ //生成任务清单
name: '__dll__[name]', //引入打包的东西,因此name需与output.library相同
path: path.resolve(__dirname, 'dist', 'manifest.json')
})
]
}
3.打包:npx webpack --config webpack.react.js,生成__dll__react.js和manifest.json。
manifest.json清单中的内容可以在__dll__react.js中找到。
4.webpack.config.js:将manifest.json清单引入
const path= require('path');
const webpack = require('webpack');
const htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
noParse: /jquery | loader/,// 不去解析这些文件的依赖库(当这些文件无依赖库时可这样设置)
rules: [
{
test: /\.js$/,
exclude: /node_module/,
include: path.resolve('src'),
use: {
loader: 'babel-loader',
options:{
presets: [
'@babel/preset-env',
'@babel/preset-react'
]
}
}
}
]
},
plugins:[
new htmlWebpackPlugin({
template: './public/index.html',
}),
new webpack.IgnorePlugin(/\.\/locale/, /moment/), //moment插件中如果使用./locale引入配置,则忽略
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, 'dist', 'manifest.json')
})
]
}
5.在src/inedx.html中引入__dll__react.js:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="root"></div>
<script src="__dll__react.js"></script>
</body>
</html>
二十六、多线程打包
1.安装happyhack
2.在webpack.config.js中配置:
。。。。
const Happypack = require('happypack');
module.exports = {
。。。。
module: {
。。。。
rules: [
{
test: /\.js$/,
exclude: /node_module/,
include: path.resolve('src'),
use: 'Happypack/loader?id=js' // 用Happypack中id=js的loader配置打包
},
{
test: /\.css$/,
use: 'Happypack?loader?id=css'
}
]
},
plugins:[
new Happypack({
id: 'js',
use:[
{
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react'
]
}
}
]
}),
new Happypack({
id: 'css',
use: ['style-loader','css-loader']
}),
。。。。
]
}
二十七、webpack中自动优化
1.import 在生产环境下会自动去除没用的代码(内置tree-shaking自动删除)
2.require会把结果放在default上,不会自动删除没有用到的代码
3.webpack中会自动忽略一下可以简化的代码
let a =1; let b =1; let c =1; let d = a+b+c;打包时会直接忽略abc,把d设为3
二十八、抽离公共代码
1.在webpack.config.js中配置:
。。。。
module.exports = {
mode: 'production', //development
。。。。
optimization: { //
splitChunks: { //分割代码块
cacheGroups: { //缓存组
common: { //公共模块抽离
chunks: 'initial', //一开始就进行抽离
minSize: 0, //文件大于0k时进行抽离
minChunks: 2 //使用两次就进行抽离
},
vendor: { //第三方模块抽离
priority: 1, //优先抽离
test: /node_modules/, //node_modules中的文件的话就处理
chunks:'initial',
minSize: 0,
minChunks: 2
}
}
}
}
}
2.创建one.js和two.js
console.log('one')
console.log('two')
3.在index.js和other.js中分别引入one.js和two.js:
import './one.js'
import './two.js'
4.打包: npm run build,生成抽离出来的代码文件common~index~other.js
二十九、懒加载
使用import()实现懒加载, 返回promise,打包生成1.js文件
1.创建src/source.js
console.log('source22222');
2.在src/index.js中:
var button = document.createElement('button');
button.innerHTML = '按钮';
button.addEventListener('click', function() {
console.log(111111);
import('./source.js').then((data) => {
console.log(data);
})
})
document.body.appendChild(button);
3.打包:npm run build,生成1.js:
(window.webpackJsonp=window.webpackJsonp||[]).push([[1],[,function(o,n){console.log("source22222")}]]);
三十、模块热替换
模块热替换:在运行时更新各种模块,而无需进行完全刷新。(搭配 webpack-dev-server在开发环境中使用)
1.在webpack.config.js中配置:
。。。。
module.exports = {
。。。。
plugins:[
。。。。
new webpack.NamedModulesPlugin(), // 显示模块的相对路径
new webpack.HotModuleReplacementPlugin()
]
}