webpack4的基础使用+从零开始构建一个vue-cli

1,832 阅读8分钟

一、webpack的基础使用

  1. 新建一个项目,手动新建一个文件夹webpack_base
  2. 使用vscode打开webpack_base文件夹
  3. 进入目录下的终端,使用npm命令初始化项目,生成package.json文件
npm init 
  1. 安装webpack与webpack-cli包 注意这里使用的是4+版本
  • 使用如下npm命令
npm i -D webpack@4 webpack-cli@4
  • 生产package.json文件

image.png

  1. 初始化项目
  • 新建src目录,在src目录下新建main.js文件
```// src/main.js
console.log("webpack_base")
  • 在package.json里面新增打包命令 注意main.js路径

image.png

  1. 执行打包命令npm run build命令进行打包 如果得到生成dist文件,则说明你已经打包成功了!

image.png

二、接下来进行webpack的基础配置

  1. 在根目录下新建build文件夹,在build文件夹下新建webpack.config.js配置文件
  2. 在配置文件中进行如下配置
//webpack.config.js
//引入核心内置模块path,用户获取文件路径等
const path = require("path")
//导出配置信息
module.exports = {
    /**
     * 设置模式:
     * development开发环境
    * production生产模式 
    * 默认值为production 
     * 也可以设置为none
     * */
    mode:'development',
    /**
     * 设置入口文件路径
    * path.resolve()由相对路径计算出绝对路径
     * __dirname是当前模块的目录名
     * */
    entry:path.resolve(__dirname,'../src/main.js'),
    /**
     * 设置输出信息
     */
    output:{
        //输出文件名
        filename:"dist.js",
       //输出文件路径
        path:path.resolve(__dirname,"../dist")
    }
}
  1. 更改打包并重新进行打包
  • 更改打包命令
"build":"webpack --config build/webpack.config.js"

image.png

  • 使用 npm run build 进行打包生成dist.js文件

image.png

  1. 缓存及html自动引入打包后的js文件

们使用 webpack 来打包我们的模块化后的应用程序,webpack 会生成一个可部署的 /dist 目录,然后把打包后的内容放置在此目录中。只要 /dist 目录中的内容部署到 server 上,client(通常是浏览器)就能够访问此 server 的网站及其资源。而最后一步获取资源是比较耗费时间的,这就是为什么浏览器使用一种名为 缓存 的技术。可以通过命中缓存,以降低网络流量,使网站加载速度更快,然而,如果我们在部署新版本时不更改资源的文件名,浏览器可能会认为它没有被更新,就会使用它的缓存版本。由于缓存的存在,当你需要获取新的代码时,就会显得很棘手。

基于以上我们不能每次打包生成同样的文件名,也不会每次打包后去跟给index.html文件里面引入的打包后的js文件 所以需要借助工具来帮我们完成这件事,这个工具就是html-webpack-plugin

  • 每次打包生成不同名称的文件

image.png

  • html自动引入生产的文件 安装html-webpack-plugin 注意安装的是4+版本
npm i -D html-webpack-plugin@4

在根目录下新建public文件夹,在public文件夹下新增index.html文件,之后在package.json文件中新增plugin配置

//引入核心内置模块path,用户获取文件路径等
const HtmlWebpackPlugin = require("html-webpack-plugin")
const path = require("path")
//导出配置信息
module.exports = {
    /**
     * 设置模式:
     * development开发环境
     * production生产模式 
     * 默认值为production 
     * 也可以设置为none
     * */
    mode:'development',
    /**
     * 设置入口文件路径
     * path.resolve()由相对路径计算出绝对路径
     * __dirname是当前模块的目录名
     * */
    entry:path.resolve(__dirname,'../src/main.js'),
    /**
     * 设置输出信息
     */
    output:{
        //输出文件名
        filename:"[name].[hash:8].js",
        //输出文件路径
        path:path.resolve(__dirname,"../dist")
    },
    plugins:[
        new HtmlWebpackPlugin({
            //设置模板
            template:path.resolve(__dirname,'../public/index.html')
        })
    ]
   
}

image.png 可以看到在生成的index.html文件中自动引入了生成的js文件

image.png

  1. 多入口文件的开发

    多入口文件开发就是设置多个入口文件和输出对应的打包后的文件,要填写多个入口文件就要将entry设置为一个对象,对象里面的属性名就是该入口文件的标识,属性值就是对于的文件路径,输出时需要在对应的html文件中引入,我们可以通过配置多个htmlwebpackplugin的方式实现。 在htmlwebpackplugin中需要设置filename来设置输出的html文件名,chunk来关联上面entry里面的入口文件

    //引入核心内置模块path,用户获取文件路径等
     const HtmlWebpackPlugin = require("html-webpack-plugin")
     const path = require("path")
     //导出配置信息
     module.exports = {
     /**
      * 设置模式:
      * development开发环境
      * production生产模式 
      * 默认值为production 
      * 也可以设置为none
      * */
     mode:'development',
     /**
      * 设置入口文件路径
      * path.resolve()由相对路径计算出绝对路径
      * __dirname是当前模块的目录名
      * */
     // entry:path.resolve(__dirname,'../src/main.js'),
     entry:{
         main:path.resolve(__dirname,'../src/main.js'),
         other:path.resolve(__dirname,'../src/other.js')
     },
     /**
      * 设置输出信息
      */
     output:{
         //输出文件名
         filename:"[name].[hash:8].js",
         //输出文件路径
         path:path.resolve(__dirname,"../dist")
     },
     plugins:[
         new HtmlWebpackPlugin({
             //设置模板
             template:path.resolve(__dirname,'../public/index.html'),
             filename:'index.html',
             chunks:['main']
         }),
         new HtmlWebpackPlugin({
             template:path.resolve(__dirname,"../public/other.html"),
             filename:'other.html',
             chunks:['other']//关联上面的entry里面的键名
         })
     ]
    
     }
    

image.png

  1. 清除残余文件,每次豆包上次生成的文件都存在,可以使用插件来清除上次打包生成的文件 安装插件clean-webpack-plugin并在package.json中配置该插件
npm i -D clean-webpack-plugin
//webpack.config.js
//省略其他,在上面的基础上 plugins里面新增清除插件
plugins:[new cleanWebpackPlugin()]

三、如何处理除js以外的其他文件

webpack默认只能处理js和json文件,要想对其他文件生效,需要加载对应的loader

  1. 引用css
  • 在我们的项目中引入css文件:根目录下新建assets静态文件夹,新增normal.css文件
  • 通常在项目中我们都使用的是css的预处理器,如果使用css预处理器,如less则需要安装对应的加载器,在assets文件夹下新增normal.less文件
//**注意版本号是否兼容**
npm i -D style-loader@2 css-loader@3  
//如果使用预处理器,则需要多安装相应的预处理器和loader
npm i -D less less-loader@5

在webpack.config.js中新增loader配置

//webpack.config.js
...//省略其他代码
module:{
//配置模块规则
    rules:[
            {
                //正则匹配所有.css结尾的文件
                test:/\.css$/,
                //匹配到之后使用的loader,从有向左解析
                use:['style-loader','css-loader']
            },
            {
                test:/\.less$/,
                user:['style-loader','css-loader','less-loader']
            }
        
    ]
}

打开生成的html文件 检查网页元素可以发现自己定义的样式

image.png

image.png

  1. 添加浏览器前缀
  • 需要借助postcss-loader autoprefixer
//注意版本号
npm i -D postcss-loader@4 autoprefixer@8
  • 在相应rule里的use添加postcss-loader
//webpack.config.js
...//省略其他代码
module:{
//配置模块规则
    rules:[
            {
                //正则匹配所有.css结尾的文件
                test:/\.css$/,
                //匹配到之后使用的loader,从有向左解析
                use:['style-loader','css-loader','postcss-loader']
            },
            {
                test:/\.less$/,
                user:['style-loader','css-loader','postcss-loader','less-loader']
            }
        
    ]
}

在项目根目录新增postcss.config.js配置文件,配置autoperfixer

//postcss.config.js
module.exports = {
    plugins:[require('autoprefixer')]
}
  1. 从js文件中抽离css文件
  • 借助mini-css-extract-plugin插件
npm i -D mini-css-extract-plugin
  • 配置插件
//webpack.config.js
//引入插件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    module:{
        rules:[
            {
                test:/\.css$/,
                //注意一定要去掉style-loader
                //注意一定要去掉style-loader
                 //注意一定要去掉style-loader
                use:[MiniCssExtractPlugin.loader,'css-loader',]
            }
        ]
    },
    plugins:[
        new MiniCssExtractPlugin({
            filename:'[name].[hash:8].css',
            chunkFilename: "[id].css",
        })
    ]
}

至此npm run build 将得到单独的css文件

image.png

整个webpack.config.js文件如下

//引入核心内置模块path,用户获取文件路径等
const path = require("path")
//清除上次打包文件插件
const { CleanWebpackPlugin } = require("clean-webpack-plugin")
//自动引入js到相应html文件插件
const HtmlWebpackPlugin = require("html-webpack-plugin")
//从js抽离出css问单独文件插件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

//导出配置信息
module.exports = {
    /**
     * 设置模式:
     * development开发环境
     * production生产模式 
     * 默认值为production 
     * 也可以设置为none
     * */
    mode:'development',
    /**
     * 设置入口文件路径
     * path.resolve()由相对路径计算出绝对路径
     * __dirname是当前模块的目录名
     * */
    // entry:path.resolve(__dirname,'../src/main.js'),
    entry:{
        main:path.resolve(__dirname,'../src/main.js'),
        other:path.resolve(__dirname,'../src/other.js')
    },
    /**
     * 设置输出信息
     */
    output:{
        //输出文件名
        filename:"[name].[hash:8].js",
        //输出文件路径
        path:path.resolve(__dirname,"../dist")
    },
    plugins:[
      
        new HtmlWebpackPlugin({
            //设置模板
            template:path.resolve(__dirname,'../public/index.html'),
            filename:'index.html',
            chunks:['main']
        }),
        new HtmlWebpackPlugin({
            template:path.resolve(__dirname,"../public/other.html"),
            filename:'other.html',
            chunks:['other']
        }),
        new CleanWebpackPlugin(),
        //从js中分离出css
        new MiniCssExtractPlugin({
            filename:'[name].[hash:8].css',
            chunkFilename: "[id].css",
        }),
        
    ],
    module:{
        //配置模块规则
        rules:[
            {
                //正则匹配所有.css结尾的文件
                test:/\.css$/i,
                //匹配到之后使用的loader,从有向左解析
                use:[MiniCssExtractPlugin.loader,'css-loader','postcss-loader']
            },
            {
                test:/\.less$/i,
                use:[MiniCssExtractPlugin.loader,'css-loader','postcss-loader','less-loader']
            }
            
        ]
        }
   
}
  1. 打包其他文件:图片,字体,媒体等

对图片、字体、媒体等静态资源一般使用url-loader进行处理后放入打包目录里面,url-loader可以将小文件转成base64,大文件则交给file-loader处理,url-loader内置了file-loader所以不需要安装file-loader

  • 在src目录下的assets新增一张图片

  • 在mian.js中引入这张图片

  • 安装url-loader

npm i -D  url-loader@4
  • 进行如下配置
rules:[
       //处理图片
            {
                //正则匹配图片格式
                test:/\.(jpe?g|png|gif)$/,
                use:[
                    {
                        loader:'url-loader',
                        options:{
                            //限制文件大小
                            limit:10240,
                            //超出上面限制之后使用的loader ext是文件本来的扩展名
                            name:'image/[name].[hash:8].[ext]'
                        }
                    }
                ]
            },
]

执行npm run build 可以看到dist文件下下面多了image文件夹,里面包含刚才在main.js里引入的图片,其他静态资源配置类似。

image.png

  1. 并不是所有浏览器都能支持es6语法,webpack需要借助babel-loader来对es5以上的语法进行处理 babel-loader需要和babel-core搭配使用
npm i -D babel-loader @babel/preset-env @babel/core
rules:[
       //处理js语法浏览器兼容问题
            {
                test:'/\.js$/',
                use:{
                    loader:'bable-loader',
                    options:{
                        presets:['@babel/preset-env']
                    }
                },
                //排除依赖下的js
                exclude:/node_modules/
            }
]

使用babel-loader不能处理如promise,generator,set,map,proxy等新的api,需要借助babel-polyfill

npm i -D bable/polyfill

更改入口文件配置

entry:{
    main:["@babel/polyfill",path.resolve(__dirname,'../src/main.js')],
    other:["@babel/polyfill",path.resolve(__dirname,'../src/other.js')]
}

以上是基于webpack4版本对js,css,静态资源等的基础配置,如果遇到问题很可能是版本兼容问题。

完整代码

四、搭建vue-cli

  1. 搭建准备
  • vue是单文件组件,使用的是.vue文件,需要使用vue-loader来解析.vue文件
  • 每个vue文件里面包含三个部分template(模板)、script(逻辑)、style(样式),需要使用vue-template-compiler来编译模板,vue-style-loader来应用样式
  1. 基于上面的项目继续搭建
  • 删除不必要的文件只留下如下项目结构

image.png

  • 修改webpack.config.js文件

image.png

image.png

  • 安装依赖
npm i -D vue-loader vue-template-compiler vue-style-loader 
npm i -S vue
  • 在webpack.config.js文件中新增如下配置。
//webpack.config.js
const vueLoaderPlugin = require("vue-loader/lib/plugin");
module.exports = {
//省略其他
    module: {
        rules: [{
            test:/\.vue$/,
            use:['vue-loader']
        }]
    },
    //配置模块如何进行解析
    resolve: {
        // 创建别名
        alias:{
            'vue$':'vue/dist/vue.runtime.esm.js',
            // 设置@引用的地址为根目录下的src
            '@':path.resolve(__dirname,"../src")
        },
        //按顺序解析以下数组后缀名的文件
        extensions:['*','.js','.json','.vue']
    },
    plugins:[
        new vueLoaderPlugin()
    ]
}
  • 通过配置webpack-dev-server使代码可以进行热更新,新增如下配置
npm i -D webpack-dev-server
const Webpack = require("webpack");
module.exports = {
    //配置开发服务器
    devServer:{
        //设置端口号
        port:8080,
        //开启热更新
        hot:true,
        //告诉服务器内容来源
        contentBase:path.join(__dirname, 'dist')
    }
}
  • 在package.json中新增打包命令

image.png

  • 接下来测试一下,在修改src目录下的main.js文件,对vue进行基础配置

image.png

  • 新建App.vue文件,写点测试代码

image.png

  • 修改public目录下的index.html文件

image.png

- [ ] 更改webpack-cli版本号为3+ !!!!!!!!

npm i -D webpack-cli@3
  • 允许npm run dev 出现如下页面

image.png

  1. 区分开发环境与生产环境 为了区分开发环境和生产环境,我们可以新增两个文件,webpack.dev.js webpack.prod.js
  • 开发环境主要是要实现热更新

  • 生产环境需要压缩代码、提取css文件、合理的sourceMap、分割代码等

    1. 使用webpack-marge合并配置采用4版本
    2. 使用copy-webpack-plugin拷贝静态资源采用5版本
    3. 使用optimize-css-assets-webpack-plugin压缩css采用5版本
    4. 使用uglifyjs-webpack-plugin压缩js采用2版本
npm i -D webpack-merge@4 copy-webpack-plugin@5 optimize-css-assets-webpack-plugin@5 uglifyjs-webpack-plugin@2
  • 在build目录下新建webpack.dev.js,并进行如下配置

image.png

  • 在build目录下新增webpack.prod.js,并进行如下配置
const path = require('path')
const webpackConfig = require('./webpack.config.js')
const WebpackMerge = require('webpack-merge')
//拷贝静态资源
const CopyWebpackPlugin = require('copy-webpack-plugin')
//压缩css
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
//压缩js
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
module.exports = WebpackMerge(webpackConfig,{
  mode:'production',
  devtool:'cheap-module-source-map',
  plugins:[
    new CopyWebpackPlugin([{
      from:path.resolve(__dirname,'../public'),
      to:path.resolve(__dirname,'../dist')
    }]),
  ],
  optimization:{
    minimizer:[
      new UglifyJsPlugin({//压缩js
        cache:true,
        parallel:true,
        sourceMap:true
    }),
    new OptimizeCssAssetsPlugin({})
    ],
    splitChunks:{
      chunks:'all',
      cacheGroups:{
        libs: {
          name: "chunk-libs",
          test: /[\\/]node_modules[\\/]/,
          priority: 10,
          chunks: "initial" // 只打包初始时依赖的第三方
        }
      }
    }
  }
})
  • 测试 更改package.json打包命令,分别打包测试

image.png

以上为整个webpack配置,参照@黄小虫的文章,如需打包优化等其他配置可以自行添加webpack相关配置。

接下来对vue-router进行配置。

五、vue-router

  1. 安装依赖 npm i vue-router

  2. 在src目录下新建两个组件 image.png

  3. 在src目录下新建router文件夹,router文件夹下新建index.js文件,编写如下代码 image.png

  4. 修改main.js文件

image.png

  1. 修改App.vue文件

image.png

  1. 测试运行

image.png

结束