一、webpack安装(4.0)
- webpack webpack-cli -D 安装前npm init -y 初始化 本地开发环境依赖安装
二、webpack可以进行0配置
- 打包工具 --- 输出后的结果(js模块化)
- 打包(支持我们的js的模块化)
三、手动配置webpack 文件名 webpack.confifg.js
- 配置入口以及打包出口
entry: './src/index.js',//打包时的入口文件 output: { filename: "bundle.js",//打包后的文件名 path: path.resolve(__dirname, 'build'),//打包后文件的路径 必须是绝对路径 __dirname当前项目的根目录 物理路径 publicPath:"./" //统一配置 给打包后的文件添加路径 可以是域名以及路径 可以按模块单独配置 } - 手动修改webpack.config.js文件名
- npx webpack --config webpack.config.my.js
- package.json里面配置脚本
scripts:{ "build": "webpack --config webpack-config.my.js" //直接执行npm run build }- npm run build -- --config webpack-config.my.js
- 安装服务的开发依赖
- npm install webpack-dev-server -D 不会真实的打包 但会进行内存中的打包,把文件写在内存中 会生成一个访问地址
- 运行命令 npx webpack-dev-server
devServer: {//开发环境下服务器的配置 port: 3000,//修改端口号 默认8080 progress: true,//内存打包时进度条 contentBase: './build',//以dist文件为静态目录打开 compress:true//启动压缩 }, - 配置通过index.html模板页面把打包生成的js塞到模板中并打包之后塞到打包build目录下 支持HTML
- 应用插件并安装插件npm install html-webpack-plugin -D
let HtmlWebpackPlugin = require('html-webpack-plugin') plugins: [//数组 放着所有的webpack插件 new HtmlWebpackPlugin({ template: "./src/index.html",//打包模板路径 filename: "index.html",//打包后的文件,默认index minify: {//压缩打包后的html页面 removeAttributeQuotes: true,// 移除属性的双引号 collapseWhitespace: true,//打包后的html折叠 }, hash:true,//打包的js添加哈希戳 }) ] output: { filename: "bundle.[hash:8].js",//打包后的文件名 加上hash让每次打包都生成不同的文件以避免缓存8代表值显示8位 path: path.resolve(__dirname, 'build'),//打包后文件的路径 必须是绝对路径 __dirname当前项目的根目录 物理路径 }, - css按模块的方式引入
- css模块基本配置
module: {//配置模块 rules: [//配置规则 css-loader处理css文件 负责解析@import这种语法 //style-loader它是把css插入到head的标签 loader的特点:希望单一 /* * loader的用法 * 1.字符串只用一个loader 多个loadeer需要用数组 默认从右向左执行 * 2.loader还可以写成对象 默认从下往上执行 * */ { test: /\.css$/,//检测css文件正则 //use:'css-loader',字符串 //use:['style-loader','css-loader'],数组 use:[ { loader: "style-loader", options: { insertAt:'top',//使模板里面的样式优先级最高 } }, 'css-loader' ] }, { //可以处理less文件 sass stylus node-sass sass-loader stylus stylus-loader test: /\.less$/,//检测css文件正则 //use:'css-loader',字符串 //use:['style-loader','css-loader'],数组 use:[ { loader: "style-loader", options: { insertAt:'top',//使模板里面的样式优先级最高 } }, 'css-loader',//解析路径以及@import 'less-loader'//把less转换成css ] } ] }- npm install mini-css-extract-plugin -D 抽离css样式插件
plugins: [//数组 放着所有的webpack插件 new HtmlWebpackPlugin({ template: "./src/index.html",//打包模板路径 filename: "index.html",//打包后的文件,默认index minify: {//压缩打包后的html页面 removeAttributeQuotes: true,// 移除属性的双引号 collapseWhitespace: true,//打包后的html折叠 }, hash:true,//打包的时候加上哈希戳 }), new MiniCssExtractPlugin({ //抽离css样式文件 filename:'css/main.css',//文件名 设置打包后的文件输出路径以及文件名 }) ], module: {//配置模块 rules: [//配置规则 css-loader处理css文件 负责解析@import这种语法 //style-loader它是把css插入到head的标签 loader的特点:希望单一 /* * loader的用法 * 1.字符串只用一个loader 多个loadeer需要用数组 默认从右向左执行 * 2.loader还可以写成对象 默认从下往上执行 * */ { test: /\.css$/,//检测css文件正则 //use:'css-loader',字符串 //use:['style-loader','css-loader'],数组 use:[ // { // loader: "style-loader", // options: { // insertAt:'top',//使模板里面的样式优先级最高 // } // }, MiniCssExtractPlugin.loader,//创建link标签引入 'css-loader' ] }, { //可以处理less文件 sass stylus node-sass sass-loader stylus stylus-loader test: /\.less$/,//检测css文件正则 //use:'css-loader',字符串 //use:['style-loader','css-loader'],数组 use:[ // { // loader: "style-loader", // options: { // insertAt:'top',//使模板里面的样式优先级最高 // } // }, MiniCssExtractPlugin.loader, 'css-loader',//解析路径以及@import 'less-loader'//把less转换成css ] } ] }- 安装autoprefixer自动添加浏览器前缀 postcss-loader 处理autoprefixer的loader
- npm install postcss-loader autoprefixer -D 自动添加浏览器前缀以及样式
module: {//配置模块 rules: [//配置规则 css-loader处理css文件 负责解析@import这种语法 //style-loader它是把css插入到head的标签 loader的特点:希望单一 /* * loader的用法 * 1.字符串只用一个loader 多个loadeer需要用数组 默认从右向左执行 * 2.loader还可以写成对象 默认从下往上执行 * */ { test: /\.css$/,//检测css文件正则 //use:'css-loader',字符串 //use:['style-loader','css-loader'],数组 use:[ // { // loader: "style-loader", // options: { // insertAt:'top',//使模板里面的样式优先级最高 // } // }, MiniCssExtractPlugin.loader,//创建link标签引入 'css-loader', 'postcss-loader'//解析css之前添加 ] }, { //可以处理less文件 sass stylus node-sass sass-loader stylus stylus-loader test: /\.less$/,//检测css文件正则 //use:'css-loader',字符串 //use:['style-loader','css-loader'],数组 use:[ // { // loader: "style-loader", // options: { // insertAt:'top',//使模板里面的样式优先级最高 // } // }, MiniCssExtractPlugin.loader, 'css-loader',//解析路径以及@import 'postcss-loader',//解析css之前添加 'less-loader'//把less转换成css ] } ] } //并创建postcss.config.js文件 module.exports = { plugins:[require('autoprefixer')]//放用到的插件 }- npm install optimize-css-assets-webpack-plugin 压缩静态资源 使用了这插件覆盖了之前js的压缩,也就是js不会压缩必须使用插件去压缩uglifyjs-webpack-plugin
optimization: {//优化项 生产环境下生效 开发环境下不生效 minimizer:[ new OptimizeCSSAssetsPlugin(), new UglifyJsPlugin({ cache: true,//缓存 parallel: true,//支持并发打包 sourceMap:true//源码映射 }) ] }, - babel-loader es6语法转换为es5语法的loader @babel/core babel核心模块 @babel/preset-env 高级语法转为低级语法 npm install @babel/plugin-proposal-class-properties -D 支持es7类的用法
{
test:/\.js$/,
use:{
loader:'babel-loader',
options: {//用babel-loader需要把es6语法转换为es5语法
presets:[//预设
'@babel/preset-env'
],
plugins:[
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose" : true }]
]
}
}
},
- 处理js语法以及校验
- npm install --save-dev @babel/plugin-transform-runtime 开发环境下
- npm install --save @babel/runtime 生产环境下
{ test:/\.js$/, use:{ loader:'babel-loader', options: {//用babel-loader需要把es6语法转换为es5语法 presets:[ '@babel/preset-env' ], plugins:[ ["@babel/plugin-proposal-decorators", { "legacy": true }], ["@babel/plugin-proposal-class-properties", { "loose" : true }], "@babel/plugin-transform-runtime" ] } }, include:path.resolve(__dirname,'src'),//校验src下面的js exclude:/node_modules/,//排除modules下面js }, - 实例上面的方法默认不会帮解析 @babel/polyfill require('@babel/polyfill')
- eslint校验js语法 npm install eslint eslint-loader
{
test: /\.js$/,
use: {
loader: 'eslint-loader',
options:{
enforce:'pre'//previous post 后面 强制在js转换之前执行校验语法
}
}
},
- webpack中第三方模块的使用
- npm install jquery
第一种 //通过内联loader把jquery暴露出全局的$ npm install expose-loader import $ from 'expose-loader?$!jquery' //expose-loader //暴露全的loader 内联的loader pre 前面执行的loader 普通loader 后者post loader console.log(window.$) rules: 第二种 { test:require.resolve('jquery'), use:'expose-loader?$' }, import $ from 'jquery' 第三种 在每个模块中注入$ let webpack = require('webpack') 通过webpack插件 new Webpack.ProvidePlugin({ 在每个模块中注入$ $:'jquery' }) 第四种 引入不打包 cdn引入 import $ from 'jquery' //不属于plugin插件配置 external:{//引用一个库,但是又不想让webpack打包 jquery:'$' }, - webpack打包图片
- 在js中创建图片来引入 必须以模块的形式引入 require或者import引入
//file-loader npm install file-loader 默认会在内部生产一张图片到build目录下,并把生产的图片的名字返回来 import logo from './a01.jpg' //把图片引入,返回的结果是一个新的图片地址 console.log(logo); let image = new Image(); image.src = logo; //就是一个字符串 document.body.appendChild(image) { test: /\.(png|jpg|gif)$/, use:'file-loader' },- 在css引入背景图片
可以直接普通的去使用(background:url('./logo.png'))- html中通过img使用 npm install html-withimg-loader html-withimg-loader编译html页面中的img编译图片路径
{ test: /\.html$/, use:'html-withimg-loader' },- 转换为base64 url-loader npm install url-loader
{ test: /\.(png|jpg|gif)$/, //做一个限制 当我们的图片 小于多少k的时候 用base64来转换 不然使用file-loader展示真实的图片 use:{ loader: 'url-loader', options: { limit:200*1024,//限制图片的大小 outputPath:'/img/',//设置打包之后文件分类目录 publicPath:"http://baidu.com" //配置图片的路径 可以在output里面统一配置,也可以单独配置 } } },
四、打包多页面应用
1.基本配置以及应用
let path = require('path')
let HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode:'development',
//多入口
entry: {
home: './src/index.js',
other: './src/other.js'
},
output:{
filename: '[name].js',
path: path.resolve(__dirname,'bundle')
},
plugins: [ //new 两次
new HtmlWebpackPlugin({
template: "./index.html",
filename: "home.html",
chunks: ['home'] //代码块
}),
new HtmlWebpackPlugin({
template: "./index.html",
filename: "other.html",
chunks: ['other','home'] //代码块
}),
]
}
- sourceMap的使用
//1. 源码映射 会单独生成一个sourcemap文件,出错了 辉表示当前报错的列和行 大切全
//devtool: "source-map",//增加映射文件 可以帮助我们调试源代码
//2. 不会产生单独的文件 但是会显示行和列
//devtool: "eval-source-map",
//3.不会产生列 但是是一个单独的映射文件
//devtool: "cheap-module-source-map",//产生后可以保留起来调试
//4. 不会产生文件 集成在打包后的文件中 不会产生列
devtool: "cheap-module-eval-source-map",
- watch的用法(监控代码变化 并且实时编译)
watch: true,
watchOptions: {//监控选项
poll: 1000,//每秒监控 问1000要不要更新
aggregateTimeout:500,//防抖 我一直输入代码 500毫秒打包一次
ignored: /node_modules/,//不需要进行监控文件
},
- webpack小插件
1. cleanWebpackPlugin //删除文件
new CleanWebpackPlugin('./bundle') //删除那个文件 再产生
2. copyWebpackPlugin //拷贝文件
new CopyWebpackPlugin([
{
from:'doc', //从哪里copy到哪里去
to:'./'
}
]) //删除那个文件 再产生
3. bannerPlugin 内置模块 需要引入webpack模块
new webpack.BannerPlugin('make 2019')
- 跨域问题
//第二种 我们前端只想单纯的模拟数据
before(app){ //提供的方法 钩子
app.get('/user',(req,res) => {
res.json({
name:"不不不11"
})
});
},
//第一种
proxy: {
'/api': {
target: "http://localhost:3000",//配置一个代理 以api开头的都去道理服务上面找
pathRewrite: {
'/api': '' //替换api为空
}
},
},
服务端启动webpack
//npm install webpack-dev-middleware -D 中间件 在服务端启动webpack
let webpack = require('webpack')
let middle = require('webpack-dev-middleware')
let config = require('./webpack.config.js')
let compiler = webpack(config) //webpack经过处理
app.use(middle(compiler))
- resolve属性配置
resolve: { //解析 第三方包
modules: [path.resolve('node_modules')], //当前目录下查找 不回去上级目录下查找
// alias: {//别名
// bootstrap:'bootstrap/dist/css/bootstrap.css'
// },
//mainFields: ['style','main'], //主入口 先找style style找不到再找main
//mainFiles: [] , //入口文件的名字 默认找index.js
extensions: ['.css','.js','.json']
}
- 定义环境变量
new webpack.DefinePlugin({//定义插件
DEV:JSON.stringify('dev')
})
- 区分不同环境
npm install webpack-merge -D 合并
创建开发环境 webpack.dev.js
let merge = require('webpack-merge')
let base = require('./webpack.base.js') //开发环境以及生成环境共用的配置
module.exports = merge(base,{
mode:"development",
devServer:{ //生成环境配置
}
})
创建生成环境webpack.pro.js
let merge = require('webpack-merge')
let base = require('./webpack.base.js') //开发环境以及生成环境共用的配置
module.exports = merge(base,{ //开发环境配置
mode:"production",
optimization:{
}
})
五、webpack优化
- noParse:/jquery/, //不去解析jquery依赖库
module: {
noParse:/jquery/, //不去解析jquery依赖库
rules: [
{
test:/.\.js$/,
exclude:/node_nodule/,//排除node_modules中的js
include:path.resolve('src'), //包含在src的js
use: {
loader: "babel-loader",
options: {
presets:[
"@babel/preset-env",
"@babel/preset-react"
]
}
}
}
]
}
- IgnorePlugin 插件 webpack内置插件 忽略插件
new Webpack.IgnorePlugin(/\.\/locale/,/moment/), //只引入moment中中文语言包 忽略其他的
- dllPlugin 动态链接库 抽离第三方库 不需要打包 先独立的进行打包第三方库 我们打包好的文件之后直接进入打包好的第三方库文件
创建webpack.config.react.js
let path = require('path')
let Webpack = require('webpack')
module.exports = {
mode: "development",
entry: ['react','react-dom'], //要打包的第三方包名
// entry: './src/test.js',
output: {
filename: '_dll_[name].js', //产生的文件名
path: path.resolve(__dirname,'dist'),
//library: 'ab',//打包后的文件返回值赋值给a
library: '_dll_[name]',//打包后的文件返回值赋值给a 变量名与产生的文件名一致
//libraryTarget:'commonjs' //模块输出 umd模式 var
},
plugins: [
new Webpack.DllPlugin({
name:"_dll_[name]",//name === library
path:path.resolve(__dirname,'dist','manifest.json') //产生清单的路径
})
]
}
webpack.config.js
new Webpack.DllReferencePlugin({
manifest: path.resolve(__dirname,'dist','manifest.json')
})
- 多线程打包 happypack 可以实现多线程来打包 第三方插件
webpack.config.js
new Happypack({ //调用下面的loader去打包
id:'js',
use: [{
loader: "babel-loader",
options: {
presets:[
"@babel/preset-env",
"@babel/preset-react"
]
}
}]
})
rules: [
{
test:/.\.js$/,
// use: {
// loader: "babel-loader",
// options: {
// presets:[
// "@babel/preset-env",
// "@babel/preset-react"
// ]
// }
// }
use:'Happypack/loader?id=js' //使用happypack/loader进行打包 并标识是js
}
]
- 多页面打包时抽取公共代码
webpack.config.js
optimization: {
splitChunks: { //分割代码块
cacheGroups: {//缓存组
common: {//公共的模块
chunks: "initial",//提取公共代码的入口
minSize: 0,//公用的字节大于0
minChunks: 2,//公用的次数
},
vendor: {
priority: 1,//权重 先抽第三方模块
test: /node_modules/, //把你抽离出来
chunks: "initial",//提取公共代码的入口
minSize: 0,//公用的字节大于0
minChunks: 2,//公用的次数
}
}
}
},
- 懒加载
index.js
let button = document.createElement('button')
button.innerHTML = "hello"
button.addEventListener('click',function () {
console.log("click");
//es6 草案中的语法 jsonp实现动态加载文件 返回的是个promise vue路由懒加载的实现原理 react
import('./source.js').then(data => {
console.log(data);
})
})
- 热更新
webpack.config.js
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
filename: "index.html"
}),
new Webpack.IgnorePlugin(/\.\/locale/, /moment/), //只引入moment中中文语言包 忽略其他的
// new Webpack.DllReferencePlugin({
// // manifest: path.resolve(__dirname,'dist','manifest.json')
// // }),
new Webpack.NamedModulesPlugin({ //指定模块更新 打印更新的模块路径
}),
new Webpack.HotModuleReplacementPlugin({ //热更新插件
})
],
devServer: {
port: 3000,
open: true,
contentBase: './dist',
hot:true //启用热更新
},
index.js
import str from './source'
console.log(str)
if(module.hot){//支持热更新
module.hot.accept('./source',() => {
let str = require('./source')
console.log(str);
})
}
版权声明:本文为sodakii原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。