1、全局安装
npm i -g webpack
2、新建空文件夹 初始化生成package.json
npm init -y
3、安装webpack-cli
npm install webpack webpack-cli --save-dev
4、创建目录和文件
初始化生成的 package.json
{
"name": "webpackpro",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12"
}
}
5、修改package.json文件
//便确保我们安装包是私有的(private),并且移除 main 入口。这可以防止意外发布你的代码。
{
"name": "webpackpro",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"build": "webpack --mode production",
"dev": "webpack --mode development"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12"
}
}
6、配置webpack.config.js
6.1 配置出入口文件:
const path = require('path')
module.exports={
entry:"./src/main.js", //入口文件
output:{ //出口文件
filename:"[name].js",
path:path.resolve(__dirname,"dist") // __dirname绝对路径
}
}
此时运行 npm run build 便会在dist中生成打包后的文件main.js
6.2 配置plugins 自动生成html文件
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports={
mode:'development',
entry:"./src/main.js",
output:{
filename:"[name].js",
path:path.resolve(__dirname,"dist")
},
plugins: [
// new VueLoaderPlugin(),
new CleanWebpackPlugin(), //每次在打包时,文件都是已覆盖已有的,不删除多余的。执行npm run build后dist目录先被删除然后在重新根据配置生成。
new HtmlWebpackPlugin({ //自动生成一个引入了打包后JS的html
template: path.resolve(__dirname, './public/index.html'),//模板文件
filename: 'index.html'//生成的文件名称
}),
],
}
运行 npm run build 生成index.html和main.js
6.3配置devServer
安装webpack服务 自动监测代码变化并实时刷新浏览器
- npm install --save-dev clean-webpack-plugin
devServer:{
contentBase:'./dist', //服务器启动的目录
open:true, //自动打开浏览器
proxy:{ //设置代理,可用于本地mock数据,本地自己启动另外一个服务
"/api":{
target:"http://localhost:9092"
}
},
port:8083, //指定端口号
hot:true, //开启HMR(Hot Module Replacement)热模块替换,由于是webpack自带的,所以要引入webpack ,监控并更新js模块的工作vue等框架自己做了,否则需要自己手动监控
hotOnly:true
},
修改package.json
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"build": "webpack --mode production",
"dev": "webpack-dev-server --open --hot --mode development"
},
devServer中hot有时不起作用,建议写到package.json中。
open hot inline 只能在devserve或者package.json中写一个
具体原因:https://segmentfault.com/a/1190000007429897
此时运行 npm run dev 会在本地启动一个nodejs的web服务,并自动打开localhost:9000
6.4 使用source-map追踪源代码错误
devServer:{
contentBase:'./dist', //服务器启动的目录
open:true, //自动打开浏览器
proxy:{ //设置代理,可用于本地mock数据,本地自己启动另外一个服务
// "/api":{
// target:"http://localhost:9000"
// }
},
// 方便追踪源代码错误
devtool: 'source-map',
// port:9000, //指定端口号 默认8080
// hot:true, //开启HMR(Hot Module Replacement)热模块替换,由于是webpack自带的,所以要引入webpack ,监控并更新js模块的工作vue等框架自己做了,否则需要自己手动监控
// hotOnly:true
},
在编译生成的dist目录中,js代码已被重新混淆,如果出现错误,无法将错误正确定位到原始代码的对应位置,这样不方便调试生成环境的代码。如果需要精确调试生产环境代码,可通过source-map实现。(如果不需要此功能,可以跳过本节)
6.5 拆分webpack.config.js 区别开发环境和生产环境
- 安装插件拆分 npm install webpack-merge --save-dev
- 新建三个文件:
webpack.base.js (公共配置)
webpack.dev.js (开发环境配置)
webpack.prod.js (生产环境配置)
将webpack.config.js代码拆分后,可删除webpack.config.js。 - 区分生产环境和开发环境 :https://my.oschina.net/46395665/blog/3111922/print
webpack.base.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports={
mode:'development',
entry:"./src/main.js",
output:{
filename:"[name].js",
path:path.resolve(__dirname,"dist")
},
plugins: [
// new VueLoaderPlugin(),
new CleanWebpackPlugin(), //每次在打包时,文件都是已覆盖已有的,不删除多余的。执行npm run build后dist目录先被删除然后在重新根据配置生成。
new HtmlWebpackPlugin({ //自动生成一个引入了打包后JS的html
template: path.resolve(__dirname, './public/index.html'),//模板文件
filename: 'index.html'//生成的文件名称
}),
],
}
webpack.dev.js
const merge = require("webpack-merge")
const base = require("./webpack.base")
module.exports = merge(base,{
devServer:{
contentBase:'./dist', //服务器启动的目录
open:true,
proxy:{ //设置代理,可用于本地mock数据,本地自己启动另外一个服务
// "/api":{
// target:"http://localhost:9000"
// }
},
// port:9000, //指定端口号 默认8080
// hotOnly:true
},
})
webpack.prod.js
const merge = require('webpack-merge');
const base = require('./webpack.base');
module.exports = merge(base, {
// 方便追踪源代码错误
//(如果不需要该的追踪功能,可以注释掉下行代码)
devtool: 'source-map'
});
拆分完成后修改package.js
--config 指定文件 默认 webpack.config.js
"scripts": {
"build": "webpack --mode production --config webpack.prod.js",
"dev": "webpack-dev-server --open --hot --mode development --config webpack.dev.js"
},
6.6 ES6 转 ES5
- 安装插件
npm install babel-loader @babel/core @babel/preset-env --save-dev
npm install @babel/plugin-transform-runtime @babel/plugin-transform-modules-commonjs --save-dev
npm install @babel/runtime --save
webpack.base.js
module:{
rules:[
{
// es6转es5
test: /.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: [
'@babel/plugin-transform-runtime',
'@babel/plugin-transform-modules-commonjs'
]
}
}
},
]
}
6.7 加载css配置(以stylus为例)
- 安装插件
npm install style-loader css-loader --save-dev
npm install stylus-loader stylus --save-dev
webpack.base.js
module:{
rules:[
{
// es6转es5
test: /.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: [
'@babel/plugin-transform-runtime',
'@babel/plugin-transform-modules-commonjs'
]
}
}
},
/**
* 处理css模块需要两个loader:style-loader和css-loader
* css-loader工作机制:处理css模块,识别合并css模块
* style-loader工作机制:把合并的css模块放到html中head的style标签中。
*/
{
test: /.css$/,
use: [
//执行顺序:从下到上,从右到左
'style-loader', //把合并的css放到style标签
'css-loader' //先识别css并合并为一个css
]
},
/**
* 处理stylus文件需要style-loader、css-loader、stylus-loader,
* stylus-loaderr工作机制:把stylus语法转换成css,
*/
{
test: /.styl$/,
use: [
'style-loader',
'css-loader',
'stylus-loader'
]
}
]
}
执行build后,样式代码会直接打包插入到html文件中。
6.8抽离css
安装MiniCssExtractPlugin
npm install mini-css-extract-plugin --save-dev
修改webpack.base.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
//插件
plugins: [
// new VueLoaderPlugin(),
new CleanWebpackPlugin(), //每次在打包时,文件都是已覆盖已有的,不删除多余的。执行npm run build后dist目录先被删除然后在重新根据配置生成。
new HtmlWebpackPlugin({ //自动生成一个引入了打包后JS的html
template: path.resolve(__dirname, './public/index.html'),//模板文件
filename: 'index.html'//生成的文件名称
}),
//如果不想让css放在header中style标签中,我们可以使用插件来帮我们抽离css并打包输出到dist目录,此时需要去掉'style-loader'
new MiniCssExtractPlugin({
filename: '[name].css', //输出文件名
chunkFilename: '[id].css', //模块名
}),
],
module:{
rules:[
{
// es6转es5
test: /.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: [
'@babel/plugin-transform-runtime',
'@babel/plugin-transform-modules-commonjs'
]
}
}
},
/**
* 处理css模块需要两个loader:style-loader和css-loader
* css-loader工作机制:处理css模块,识别合并css模块
* style-loader工作机制:把合并的css模块放到html中head的style标签中。
*/
{
test: /.css$/,
use: [
//执行顺序:从下到上,从右到左
MiniCssExtractPlugin.loader, //抽离css替换掉style-load
// 'style-loader', //把合并的css放到style标签
'css-loader' //先识别css并合并为一个css
]
},
/**
* 处理stylus文件需要style-loader、css-loader、stylus-loader,
* stylus-loaderr工作机制:把stylus语法转换成css,
*/
{
test: /.styl$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'stylus-loader'
]
}
]
}
同时在main.js中引入css样式
此时执行 npm run build 后会在dist中生成以下文件
6.9 加载图片资源
安装插件 npm install file-loader url-loader --save-dev
{
test: /.(png|svg|jpg|gif|webp)$/,
use: [
{
loader: 'url-loader',
options: {
name:"[name]-[hash].[ext]",//[]表示占位符,name表示源文件的名字,ext是源文件的后缀,hash是复制的文件名入‘570e69d9e57c7d0203b5e30a9dd1dbdf’
// outputPath:"images/", //配置输出位置
// 图片输出的实际路径(相对于dist)
outputPath: 'images',
// 当小于某KB时转为base64
limit: 2048,
esModule: false //作用是启用CommonJS模块语法 ,否则图片地址可能会出现下方情况
}
}
]
}
6.10 集成jQuery
安装 npm install jquery --save
//添加
const webpack = require('webpack');
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}),
],
6.11 解析vue
安装 npm install -D vue-loader vue-template-compiler
webpack.base.js
const VueLoaderPlugin = require('vue-loader/lib/plugin') //引入
plugins: [
new VueLoaderPlugin()
],
module:{
rules:[
// 解析vue
{
test: /.vue$/,
loader: 'vue-loader'
}
]
}
7、vue搭建
7.1 引入vue
npm install vue
// import Vue from "vue/dist/vue.js" //写法2
import Vue from "vue" //写法1
import "./assets/reset.css"
//
// console.log(vue)
var app = new Vue({
el:"#app",
data:{
message:"没毛病"
}
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>webpack--vue</title>
</head>
<body>
<div id="app">老铁 {{message}}</div>
</body>
</html>
- 这里直接按照 写法1 引入vue后会报错:
原因: 这里引入的其实不是vue.js 而是vue.common.js。package.json 中的 main 属性决定了,当项目被引入时,输出的是哪个文件,而 vue 的 package.json 中的 main 指向的是 dist/vue.common.js。
解决方法:
1.按照 写法2 引入vue
2、按照 写法1 引入vue 的同时 配置webpack.base.js别名配置
//别名配置
resolve: {
alias: {
'vue': 'vue/dist/vue.js'
}
},
至此,会在页面输出 “老铁 没毛病”。
7.2 挂载APP页面
// import Vue from "vue/dist/vue.js"
import Vue from "vue"
import APP from "./APP.vue"
import "./assets/reset.css"
new Vue({
render: h => h(APP)
}).$mount("#app");
7.3 配置路由
安装vue-router
npm install vue-router
router/index.js
import Vue from "vue"
import VueRouter from "vue-router"
import Home from "../views/home.vue"
Vue.use(VueRouter)
const routes=[
{
path:"/home",
name:"home",
component:Home,
children:[
{
path:"/home/children",
name:"children",
component:()=>import("../views/children.vue")
}
]
},
{
path:"/home/children",
name:"children",
component:()=>import("../views/children.vue")
}
]
const router = new VueRouter({
mode:"hash",
base: process.env.BASE_URL,
routes
})
export default router
7.4 配置axios
安装 npm install axios
axios.js
import axios from "axios"
import QS from "qs"
axios.defaults.baseURL = process.env.NODE_ENV=="development" ?
"http://10.1.1.175:9001" : ""
// console.log(axios.defaults.baseURL,"vbaseURL")
axios.defaults.timeout = 10000;
axios.defaults.withCredentials = true //携带cookie
// 需要后端配置请求头
// header("Access-Control-Allow-Origin","源地址";
// header("Access-Control-Allow-Credentials", "true");
// 请求拦截器
axios.interceptors.request.use(
config=>{
// config.headers = Object.assign({}, config.headers, { token: sessionStorage.getItem("token") })
return config
},
error=>{
return Promise.reject(error)
}
)
// 响应拦截器
axios.interceptors.response.use(
res=>{
console.log(res)
return res.data
},
err=>{
console.log(err)
}
)
// get
export function get(url,data){
if(url.indexOf("?") != -1){ //防止ie浏览器缓存
url = url + "&n=" + encodeURIComponent(Math.random())
}else{
url = url + "?n=" + encodeURIComponent(Math.random())
}
return axios.get(url,{params:data})
}
// post
export function post(url,data){
return axios({
url:url,
method:"post",
data
})
}
// 表单
// By default, axios serializes JavaScript objects to JSON
export function postForm(url, data = {}) {
if (typeof data != "object") {
return
}
return axios({
url: ip + url,
method: "post",
headers: { "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" },
transformRequest: [
function(data) {
let ret = ""
for (let it in data) {
ret += encodeURIComponent(it) + "=" + encodeURIComponent(data[it]) + "&"
}
return ret
}
],
data
})
}
// put
export function put(url, data) {
return axios({
url: ip + url,
method: "put",
data
})
}
// delete
export function deletes(url, data) {
return axios({
url: ip + url,
method: "delete",
data
})
}
export default axios
http.js
import {get,post} from "@/utils/axios"
export const login = data => post("/user/login",data)
export const getTree = data => get("/dataOrder/getDestName")
home.vue
methods: {
async getTreedata(){
let tree = await getTree()
// console.log(tree,"ffffffffffffffffff")
},
// getTreedata(){
// getTree().then(res=>{
// console.log(res)
// })
// }
}