webpack

概念
本 质上,webpack是一个现代 JavaScript 应用程序的 静态模块打包器(module bundler) 。

当 webpack 处理应用程序时,它会递归地构建一个 依 赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle 。

安装
确保安装了nodejs

项目文件环境
cd mypack
// 进入你的项目目录 mypack目录可以随意自己建立

npm init  
//  初始化项目文件夹 会创建一个package.js
本地安装
npm install --save-dev webpack
npm install --save-dev webpack-cli
对于大多数项目,我们建议本地安装

准备文件
-- dist 文件生成目录
---- index.html 

-- index.js 主入口文件
-- header.js 需要被index引入的文件
#  index.html
<!DOCTYPE html>
<html lang="cn">
<head>
    <meta charset="UTF-8">
    <title>第一个webpack页面</title>
</head>
<body>
 <script src="main.js"></script>   
</body>
</html>

<!--打包好的js名称默认是main.js-->


#  index.js
import {header} from './header.js'
document.body.append(header);


#  header.js
var header =document.createElement("div");
header.innerHTML="你好webpack from header";
export {header};
执行命令 打开index.html
npx webpack index.js
// 在你的项目目录执行 这里的名称是 mypack

然后打开你的dist/index.html 查看网页文件
同时你会发现在 dist目录多个main.js这个打包生成好的js文件
使用配置文件
在项目目录 新建一个webpack.config.js webpack默认配置文件

const path = require('path')
// 引入node的 path路径模块

module.exports={
    entry:'./index.js',
    // 指定文件的入口
    output:{
        filename:'main.js',
        // 定义文件名
        path:path.resolve(__dirname,'dist')
        // 定义文件夹 
        // __dirname获取当前目录
        // path.resolve 方法将路径或路径片段的序列解析为绝对路径
    }
    // 指定打包好的出口
}
// module.export node中导出模块的意思

# 以下为纯净版本
const path = require('path')
module.exports={
    entry:'./index.js',
    output:{
        filename:'main.js',
        path:__dirname+'/dist',
    }
}
执行命令npx webpack实现打包

配置 scripts
找到package.js 配置scripts

"scripts":{
    start:  "webpack"
}
这样我们就可以执行

npm run start
// yarn start

配置模式
const path = require('path')
module.exports={
    mode:'development', //开发模式
    // mode:'production',// 产品模式
    entry:'./index.js',
    output:{
        filename:'main.js',
        path:path.resolve(__dirname,'dist')
   
产品模式打包的大小要比生产模式要小的多。

 "scripts": {
    "dev": "webpack --mode development",
    "build": "webpack --mode production"
  },
核 心概念:

入口(entry)
输出(output)
因为 index.html 文件太死了,连 js 文件都写死了

html-webpack-plugin
安装

npm install html-webpack-plugin --save-dev
使用

 
const htmlWebpackPlugin = require('html-webpack-plugin');
module.exports={   
    mode:'production',
    entry:'./src/index.js',
    output:{
        filename:'main.js',
        path:__dirname+'/dist'
    },
    plugins:[
        new htmlWebpackPlugin({
            template:'./src/index.html'
        })
    ]
}

# 项目mypack目录结构如下
src
   header.js
   index.html
   index.js
package.js
webpack.config.js
下面我再来介绍几个参数,以及它的结果。

filename: 'index.html' 默认情况下生成的 html 文件叫 index.html,但有时候你不想叫这个名字,可以改。

filename:'youIndex.html'
minify压缩 去空格

minify: {
  collapseWhitespace: true,
},
这个可以把生成的 index.html 文件的内容的没用空格去掉,减少空间。

处理css
css-loader 分析css关系-合并一个css(import)
style-loader 把css挂载到head里面
mini-css-extract-plugin 把css抽取到单独文件
optimize-css-assets-webpack-plugin用于压缩css文件,它将在webpack构建期间搜索css资源,并将优化/最小化css
less less-loader 处理less文件

npm install css-loader style-loader mini-css-extract-plugin  optimize-css-assets-webpack-plugin -D
index.js


import {header} from './header.js'
import './css/style.css'
import './css/style.less'
document.body.append(header);
webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.exports={ 
    optimization: {
        minimizer: [ new OptimizeCSSAssetsPlugin({})],
      },  
    mode:'production',
    entry:'./src/index.js',
    output:{
        filename:'main.js',
        path:__dirname+'/dist'
    },
    module:{
        rules:[
            {
                test:/\.css$/,
                use:[MiniCssExtractPlugin.loader,/* 'style-loader', */'css-loader']
            },
            {
                test:/\.less$/,
                use:[MiniCssExtractPlugin.loader,/* 'style-loader', */'css-loader','less-loader']
            }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template:'./src/index.html'
        }),
        new MiniCssExtractPlugin({
            filename: 'style.css',
            
          }),
    ]
}
webpack-dev-server
webpack-dev-server 本地服务
clean-webpack-plugin 清理dist目录

安装

npm install   clean-webpack-plugin webpack-dev-server  -D
 
webapck.config.js添加如下设置
module.exports = {
    devServer: {
        host: 'localhost', //主机地址,默认是localhost
        port: '8080', //端口号,默认8080
        open: true, //自动打开页面
        hot:true,//热更新
    },
};
package.json中添加开发环境启动指令
{
  "scripts": {
    "dev": "webpack serve"
  }
}
执行npm run dev,即可在开发环境下运行项目了

前端跨域代理
前端通过代理处理跨域问题,只适用开发环境。对于需要代理的接口,我们将接口服务器替换成devServer,由devServer来帮助我们完成代理请求。所以在项目源代码中,我们需要自行根据开发环境以及接口是否需要代理,来判断该接口请求的服务器地址是否需要换成devServer的地址。

webpack.config.js添加如下配置
module.exports = {
    devServer: {
        proxy: {
            //哪些访问需要代理转发
            '/api': {
                target: 'http://47.110.129.207',//目标服务器
                changeOrigin: true, 
                secure: false,  
                credentials: 'include', 
                pathRewrite: {
                    '^/api': '' //重写路径,不需要重写则为‘’
                }
            }
        }
    }
}
webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports={
    devServer: {
        contentBase: './dist',
     },
    optimization: {
        minimizer: [ new OptimizeCSSAssetsPlugin({})],
      },  
    // mode:'production',
    entry:'./src/index.js',
    output:{
        filename:'main-[hash].js',
        path:__dirname+'/dist'
    },
    module:{
        rules:[
            {
                test:/\.css$/,
                use:[MiniCssExtractPlugin.loader,/* 'style-loader', */'css-loader']
            },
            {
                test:/\.less$/,
                use:[MiniCssExtractPlugin.loader,/* 'style-loader', */'css-loader','less-loader']
            }
        ]
    },
    plugins:[
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            template:'./src/index.html'
        }),
        new MiniCssExtractPlugin({
            filename: 'style.css',
            
          }),
    ]
}
图片与文件处理

file-loader可以解析项目中的url引入(不仅限于css)使之指向正确的文件

url-loader 会将小图片生成base64编码格式(url-loader封装了file-loader)

image-webpack-loader 插件可将大的图片进行压缩从而缩小打包体积

html-loader html 代码里处理 img 标签的 loader。

style.css

@import '../assets/font/iconfont.css';

div{ color:red;}
body{ background-image: url('../assets/sun.jpg');}

index.js

import {header} from './header.js'
import './css/style.css'
import './css/style.less'
import pic from './assets/pic1.jpg'
document.body.append(header);

var img = new Image();
img.src=pic;
 

// img.src=pic;
document.body.append(img);
var box = document.createElement("div");
box.innerHTML='<span class="iconfont icon-shouye1"></span> <span class="iconfont icon-shouye"></span>';
document.body.append(box);
webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports={
    devServer: {
        contentBase: './dist',
     },
    optimization: {
        minimizer: [ new OptimizeCSSAssetsPlugin({})],
      },  
    // mode:'production',
    entry:'./src/index.js',
    output:{
        filename:'main-[hash].js',
        path:__dirname+'/dist'
    },
    module:{
        rules:[
            
            {
                test: /\.(png|jpg|gif|jpeg|ico)$/,
                use:[{loader:'url-loader',options:{limit:50000,name: 'img/[name].[hash:5].[ext]'},'image-webpack-loader']
            },
            {
                test:/\.css$/,
                use:[MiniCssExtractPlugin.loader,/* 'style-loader', */'css-loader']
            },
            {
                test:/\.(eot|woff2|woff|ttf|svg)/,
                use:[{loader:'url-loader',options:{limit:10,name: 'font/[name].[hash:5].[ext]'}}],
            },
            {
                test:/\.less$/,
                use:[MiniCssExtractPlugin.loader,/* 'style-loader', */'css-loader','less-loader']
            }
        ]
    },
    plugins:[
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            template:'./src/index.html'
        }),
        new MiniCssExtractPlugin({
            filename: 'style.css',
            
          }),
    ]
}
设置目录别名
module.exports = {
    resolve: {
        alias: {
            '@': path.resolve(__dirname, './src'), //设置@为src目录的别名
        }
    },
};
public公共静态资源目录拷贝
npm install --save-dev copy-webpack-plugin
webpack.config.js添加如下配置

const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
    plugins: [
        new CopyWebpackPlugin(  // 设置静态目录(拷贝文件到另外一个文件夹)
            {patterns:[  
                // { from: __dirname+'/public', to: __dirname+'/dist' },
                //from 从, to 到 __dirname 当前目录
                { from: __dirname+'/../src/static', to: __dirname+'/dist/static' },
             ],
            }
        ),
    ],
};
参数说明

rom  定义要拷贝的源文件            from:__dirname+'/public'
to      定义要拷贝到的目标文件夹  to: __dirname+'/dist/public'
toType  file 或者 dir                        可选,默认是文件
force   强制覆盖前面的文件            可选,默认是文件
context                                            可选,默认base   context可用specific  context
flatten  只拷贝指定的文件               可以用模糊匹配
ignore  忽略拷贝指定的文件            可以模糊匹配
babel 与react
@babel/core-babel核心模块
@babel/preset-env-编译ES6等
@babel/preset-react-转换JSX

cnpm i babel-loader @babel/core @babel/preset-env  @babel/plugin-transform-runtime   @babel/preset-react -D

 @babel/plugin-transform-runtime: 避免 polyfill 污染全局变量,减小打包体积
 @babel/polyfill: ES6 内置方法和函数转化垫片

cnpm i @babel/polyfill @babel/runtime -D

main.js

import ReactDom from 'react-dom'
import React,{Component} from 'react'
class App extends Component{
    constructor(props){
        super(props);
        this.state={num:1}
    }
    render(){
        return (<div>react <button onClick={
            ()=>{this.setState({num:++this.state.num})}
        }>{this.state.num}</button></div>)
    }
}
ReactDom.render(<App/>,document.getElementById("root")) 
webpack.config.js


    test: /\.(js|jsx)$/, 
    use:['babel-loader'],
    exclude: /node_modules/ 
},
.bablerc

{
  "presets": ["@babel/preset-env","@babel/preset-react"],
}
压缩
optimize-css-assets-webpack-plugin css优化压缩

const TerserPlugin = require("terser-webpack-plugin");

const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

 minimizer: [ 
                 
                new optimizeCssAssetsWebpackPlugin({}),                
                new TerserPlugin()
                
                ],
代码分割
optimization: {
    splitChunks: {
        chunks: "all", 
        // 所有的 chunks 代码公共的部分分离出来成为一个单独的文件},
}, 
sourceMap
当错误了,能够知道源代码在那一行 sourceMap 他是一个map关系,他知道dist/main。就是文件96行错误,对应src目录下index.js第一行

devtool:'cheap-module-eval-source-map',
建议
// development:'cheap-module-eval-source-map'
// production:'cheap-module-source-map'
按需导入js
等需要的时候异步加载 js 需要安装 插件

cnpm install @babel/plugin-syntax-dynamic-import -D

配置 babelrc plugins

{
  "presets": ["@babel/preset-env","@babel/preset-react"],
  "plugins":["@babel/plugin-syntax-dynamic-import"]
 
}
在js使用

function getComponent(){
    return import(/* webpackChunkName:"jquery" */'jquery').then(({default:$})=>{
       return $;
    })
}
getComponent().then($=>{
    var el = $("<div>你好jquery</div>");
    $("body").append(el);
    el.click(()=>{
        alert("你好");
    })
    
})

也可以这么写

import('jquery')
.then(({default:$})=>{
    var el = $("<div>你好jquery</div>");
    $("body").append(el);
    el.click(()=>{
        alert("你好");
    })
    
})  
Prefetch
Prefetch是告诉浏览器这是一个在未来可能使用到的资源。 浏览器通常会在空闲状态取得这些资源,在取得资源之后搁在HTTP缓存以便于实现将来的请求

import时增加一条魔法注释即可:

 document.body.οnclick=()=>getJq();
 function getJq(){
    import( /* webpackChunkName:"jquery", webpackPrefetch: true  */ 'jquery').then(({default:$})=>{
         
        $("div").click(()=>{
            alert("你好");
        })
    })
 }

html标签页也可以实现

<link href=css/category.f436a150.css rel=prefetch>
<link href=js/about.d1393457.js rel=prefetch>
综合案例

 getJQ(){
        import(/* webpackChunkName:"jquery",webpackPrefetch:true */"jquery")
        .then(({default:$})=>{
             
              alert($("body").text())
        })
    }
//  构造函数
   render(){
       return(<div onClick={this.getJQ}> 你好react 我喜欢你</div>)
   }
环境变量
scripts:{
    "dev":"webpack-dev-server --config wepack.dev.js",
    "build":"webpack --config webpack.prod.js"
   //"build": "webpack --mode production --env.production",
}
module.exports =(evn,avg)=>{console.log(avg);return({})}
const merge = require("webpack-merge")
const devconfig = {}
const commonConfig = require("./webpack.com.js");
 

module.exports = (env)=>{
    if(env&&env.production){
        return merge(commonConfig,prod)
    }else{
        return merge(commonConfig,devConfig)
    }
    
}


Entry 与Output的配置
entry:'./src/index.js'
entry:{
    main:'./src/index.js',
    sub:'./src/index.js'
},
output:{
    publicPath:'http://www.js.com',
    // 配置根目录 默认是/ 可以配成相对目录./
    filename:'[name][hash].[ext ]'
    path:path.resolove(__dirname,'dist')
}
tree shaking
按需导入内容(摇树)
比如模块里面有个 a,b 两个模块,你只使用一个a 那么就导入a

webpack.config.js 配置

plugins:[
    optimization:{
        usedExports:true
    }
]

package.json 配置 // 忽略掉css 按需导入。

"name":"lesson"
"sideEffects":["@babel/polly-fill","*.css"],
"sideEffects":false,      
单vue文件的加载,以及babel的使用
安装依赖,用到的依赖比较多
npm install --save vue
npm install --save-dev vue-loader
npm install --save-dev vue-style-loader
npm install --save-dev vue-template-compiler
npm install --save-dev vue-hot-reload-api


npm install --save-dev @babel
npm install --save-dev @babel/preset-env
npm install --save-dev babel-loader
npm install --save-dev babel/core


 
npm i vue -S
npm i vue-loader  vue-style-loader vue-template-compiler vue-hot-reload-api -D
因为我们安装的 babel 是 6.x 版本,而它所对应的 babel-loaderl 版本必须是 7.x,所以在命令行中,我们明确指定了版本号。如果版本不对应,就会抛出 Cannot find module '@babel/core' 错误。

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
    entry: './src/main.js',
    output: {
        filename: 'js/[name]-[hash].js',//打包出的脚本文件全部放进dist下的js目录
        path: path.resolve(__dirname, 'dist'),
        publicPath: '/',//使用绝对路径
    },
    module: {
        rules: [{ //vue 解析
            test: /\.vue$/,
            loader: 'vue-loader',
            options: {
                loaders: { //开发环境使用style-loader打包
                    css: [process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', 'css-loader'],
                    scss: [process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', 'css-loader, 'sass-loader']
                }
            }
        }, { //js 解析
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/,
        }, {
            test: /\.css$/,
            //开发环境使用style-loader打包
            use: [process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', 'css-loader']
        }, {
            test: /\.scss$/,
            //开发环境使用style-loader打包
            use: [process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', 'css-loader', 'sass-loader']
        }, {
            test: /\.(png|jpg|gif)$/,
            use: [{
                loader: 'file-loader',
                options: {
                     name: 'images/[name]-[hash].[ext]',//所有图片放进images目录
}
            }]
        }]
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: 'myWebpack',
            filename: 'index.html',
            template: './public/index.html'
        }),
        new MiniCssExtractPlugin({
            filename: "[name]-[hash].css",//所有抽离出的样式文件,放进css目录
            chunkFilename: "vue-[name]-[hash].css"
        }),
        new VueLoaderPlugin()
    ],
};
配置babel
babel 是新一代 JavaScript 语法的编译器 。 可以让我们放心地使用大部分 JavaScript 新的标准语法,代码会通过编译,生成兼容绝大多数主流浏览器的代码 。 在项目工程脚手架中,一般会使用 .babelrc 文件,来配置一些基本参数,配合 webpack 进行打包压缩 。

在项目根目录,创建 .babelrc 文件,内容如下:

{
 "presets": ["@babel/preset-env","@babel/preset-react"],
 
}
属性说明 presets 指定预设转码器;

babel6 有这些值可选:es2015 ,stage-0 , stage-1 ,stage-2 , stage-3 ,react。 plugins 插件。这里安装了 transform-runtime 插件。 comments 在生成的文件中,是否带注释。

之所以使用了 transform-runtime 插件,是因为 babel 在转换 ES2015 语法为 ECMAScript 5 的语法时,它需要一些辅助函数,例如 _extend。babel 默认会将这些辅助函数内联到每一个 js 文件里,这样文当件多的时候,项目就会很大。所以 babel 提供了 transform-runtime 插件来将这些辅助函数 “搬” 到一个单独的模块 babel-runtime 中,通过这种方式就能有效地减少项目文件。

编写 App.vue 文件
在根目录下的src目录中,新建一个 App.vue

在main.js中引用 App.vue 组件

// 引入 Vue 框架
import Vue from 'vue'

//引入 App.vue 组件
import App from './App.vue'

new Vue({
    el: '#app',
    render: h => h(App)
})
查看效果
执行npm run build     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值