• 教你用webpack搭一个vue脚手架[超详细讲解和注释!](转载)


     

    1.适用人群

        1.对webpack知识有一定了解但不熟悉的同学.
        
        2.女同学!!!(233333....)

    2.目的

    在自己对webpack有进一步了解的同时,也希望能帮到一些刚接触webpack的同学.
    脚手架已放上github,不想听我啰嗦的同学可以直接去download或clone下来看哦.
    
    脚手架里都有详细注释!
    

    https://github.com/webfansplz...

    觉得有帮助到你的同学给个star哈,也算是对我的一种支持!

    3.脚手架结构

    ├── build                       构建服务和webpack配置
        |—— build.js                webpack打包服务
        |—— webpack.base.conf.js    webpack基本通用配置
        |—— webpack.dev.conf.js     webpack开发环境配置
        |—— webpack.prod.conf.js    webpack生产环境配置
    ├── config                      构建项目不同环境的配置
    ├── public                      项目打包文件存放目录
    ├── index.html                  项目入口文件
    ├── package.json                项目配置文件
    ├── static                       静态资源
    ├── .babelrc                    babel配置文件
    ├── .gitignore                  git忽略文件
    ├── postcss.config.js           postcss配置文件
    ├── src                         项目目录
        |—— page                    页面组件目录
        |—— router                  vue路由配置
        |—— store                   vuex配置
        |—— App.vue                 vue实例入口
        |—— main.js                 项目构建入口
    
    

    4.配置npm scripts

    4.1 生成package.json文件,配置npm scripts.

    4.1.1 使用 npm init 命令,生成一个package.json文件!

    npm init

    4.1.2 全局安装webpack和webpack-dev-server

    npm install webpack webpack-dev-server -g

    4.1.3 在项目目录下安装webpack和webpack-dev-server

    npm install webpack webpack-dev-server -D

    4.1.4 进入package.json配置npm scripts命令

      "scripts": {
        "dev": "webpack-dev-server  --config build/webpack.dev.conf.js",
        "start": "npm run dev",
        "build": "node build/build.js"
      }
    
      通过配置以上命令:
      我们可以通过npm start/npm run dev在本地进行开发,
      scripts.dev命令解读:
      通过webpack-dev-server命令 启动build文件夹下webpack.dev.conf.js。
      也可以通过npm run build 打包项目文件进行线上部署.
      scripts.build命令解读:
      通过node命令构建build文件夹下的build.js。
      命令的配置可以根据自己脚手架的配置文件位置和名称不同修改哦!

    5.构建脚手架目录

    同学们可以通过自己的习惯和喜爱搭建自己的脚手架目录,下面讲解以上面脚手架结构为准!

    6.构建config/config.js

    6.1 该文件主要用来配置构建开发环境和生产环境差异化的参数.
    6.2

    const _path = require("path");
    const ExtractTextPlugin = require("extract-text-webpack-plugin");
    
    //vue-loader基本配置
    const baseVueLoaderConf = {
      //引入postcss插件
      postcss: {
        config: {
          path: _path.resolve("../")
        }
      },
      //转为require调用,让webpack处理目标资源!
      transformToRequire: {
        video: "src",
        source: "src",
        img: "src",
        image: "xlink:href"
      }
    };
    
    //vue-loader 开发环境配置
    const devVueLoaderConf = Object.assign({}, baseVueLoaderConf, {
      //loaders
      loaders: {
        css: ["vue-style-loader", "css-loader"],
        less: ["vue-style-loader", "css-loader", "postcss-loader", "less-loader"]
      },
      cssSourceMap: true
    });
    
    //vue-loader 生产环境配置
    const buildVueLoaderConf = Object.assign({}, baseVueLoaderConf, {
      //loaders
      loaders: ExtractTextPlugin.extract({
        use: ["css-loader", "postcss-loader", "less-loader"],
        fallback: "vue-style-loader"
      }),
      cssSourceMap: false
    });
    
    //开发/生产环境 配置参数!
    module.exports = {
      dev: {
        publicPath: "/",
        devtoolType: "cheap-module-eval-source-map",
        vueloaderConf: devVueLoaderConf,
        host: "localhost",
        port: "1234",
        proxyTable: {}
      },
      build: {
        publicPath: "/",
        devtoolType: "source-map",
        vueloaderConf: buildVueLoaderConf,
        staticPath: "static"
      }
    };
    

    7.构建build/webpack.base.conf.js

    7.1 此文件主要是webpack开发环境和生成环境的通用配置.

    7.2

    "use strict";
    
    //引入node path路径模块
    const path = require("path");
    //引入webpack生产环境配置参数
    const prodConfig = require("../config").build;
    
    //拼接路径
    function resolve(track) {
      return path.join(__dirname, "..", track);
    }
    //资源路径
    function assetsPath(_path) {
      return path.join(prodConfig.staticPath, _path);
    }
    
    //webpack 基本设置
    
    module.exports = {
      //项目入口文件->webpack从此处开始构建!
      entry: path.resolve(__dirname, "../src/main.js"),
      //配置模块如何被解析
      resolve: {
        //自动解析文件扩展名(补全文件后缀)(从左->右)
        // import hello from './hello'  (!hello.js? -> !hello.vue? -> !hello.json)
        extensions: [".js", ".vue", ".json"],
        //配置别名映射
        alias: {
          // import Vue from 'vue/dist/vue.esm.js'可以写成 import Vue from 'vue'
          // 键后加上$,表示精准匹配!
          vue$: "vue/dist/vue.esm.js",
          "@": resolve("src"),
          utils: resolve("src/utils"),
          components: resolve("src/components"),
          public: resolve("public")
        }
      },
      module: {
        //处理模块的规则(可在此处使用不同的loader来处理模块!)
        rules: [
          //使用babel-loader来处理src下面的所有js文件,具体babel配置在.babelrc,主要是用来转义es6
          {
            test: /.js$/,
            use: {
              loader: "babel-loader"
            },
            include: resolve("src")
          },
          //使用url-loader(file-loader的一个再封装)对引入的图片进行编码,此处可将小于8192字节(8kb)的图片转为DataURL(base64),
          //大于limit字节的会调用file-loader进行处理!
          //图片一般发布后都是长缓存,故此处文件名加入hash做版本区分!
          {
            test: /.(png|jpe?g|gif|svg)(?.*)?$/,
            loader: "url-loader",
            options: {
              limit: 8192,
              name: assetsPath("img/[name].[hash:8].[ext]")
            }
          }
        ]
      }
    };
    

    8.构建 build/webpack.dev.conf.js

    8.1 该文件主要用于构建开发环境

    8.2

    "use strict";
    //引入node path路径模块
    const path = require("path");
    //引入webpack
    const webpack = require("webpack");
    //引入webpack开发环境配置参数
    const devConfig = require("../config").dev;
    //引入webpack基本配置
    const baseConf = require("./webpack.base.conf");
    //一个webpack配置合并模块,可简单的理解为与Object.assign()功能类似!
    const merge = require("webpack-merge");
    //一个创建html入口文件的webpack插件!
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    //一个编译提示的webpack插件!
    const FriendlyErrorsPlugin = require("friendly-errors-webpack-plugin");
    //发送系统通知的一个node模块!
    const notifier = require("node-notifier");
    //将webpack基本配置与开发环境配置合并!
    const devConf = merge(baseConf, {
      //项目出口,webpack-dev-server 生成的包并没有写入硬盘,而是放在内存中!
      output: {
        //文件名
        filename: "[name].js",
        //html引用资源路径,在dev-server中,引用的是内存中文件!
        publicPath: devConfig.publicPath
      },
      //生成sourceMaps(方便调试)
      devtool: devConfig.devtoolType,
      //
      //启动一个express服务器,使我们可以在本地进行开发!!!
      devServer: {
        //HMR控制台log等级
        clientLogLevel: "warning",
        // 热加载
        hot: true,
        //自动刷新
        inline: true,
        //自动打开浏览器
        open: true,
        //在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html
        historyApiFallback: true,
        //主机名
        host: devConfig.host,
        //端口号
        port: devConfig.port,
        //配置反向代理解决跨域
        proxy: devConfig.proxyTable,
        //为你的代码进行压缩。加快开发流程和优化的作用
        compress: true,
        // 在浏览器上全屏显示编译的errors或warnings。
        overlay: {
          errors: true,
          warnings: false
        },
        // 终端输出的只有初始启动信息。 webpack 的警告和错误是不输出到终端的
        quiet: true
      },
      module: {
        //处理模块的规则(可在此处使用不同的loader来处理模块!)
        rules: [
          //使用vue-loader处理以vue结尾的文件!
          {
            test: /.vue$/,
            loader: "vue-loader",
            options: devConfig.vueloaderConf
          },
          //使用vue-style-loader!css-loader!postcss-loader处理以css结尾的文件!
          {
            test: /.css$/,
            use: [
              "vue-style-loader",
              {
                loader: "css-loader",
                options: {
                  sourceMap: true
                }
              },
              {
                loader: "postcss-loader",
                options: {
                  sourceMap: true
                }
              }
            ]
          },
          //使用vue-style-loader!css-loader!postcss-loader处理以less结尾的文件!
          {
            test: /.less$/,
            use: [
              "vue-style-loader",
              {
                loader: "css-loader",
                options: {
                  sourceMap: true
                }
              },
              {
                loader: "less-loader",
                options: {
                  sourceMap: true
                }
              },
              {
                loader: "postcss-loader",
                options: {
                  sourceMap: true
                }
              }
            ]
          }
        ]
      },
      plugins: [
        //开启HMR(热替换功能,替换更新部分,不重载页面!)
        new webpack.HotModuleReplacementPlugin(),
    
        //显示模块相对路径
        new webpack.NamedModulesPlugin(),
    
        //编译出错时,该插件可跳过输出,确保输出资源不会包含错误!
        // new webpack.NoEmitOnErrorsPlugin(),
    
        //配置html入口信息
        new HtmlWebpackPlugin({
          title: "hello,xc-cli!",
          filename: "index.html",
          template: "index.html",
          //js资源插入位置,true表示插入到body元素底部
          inject: true
        }),
    
        //编译提示插件
        new FriendlyErrorsPlugin({
          //编译成功提示!
          compilationSuccessInfo: {
            messages: [
              `Your application is running here: http://${devConfig.host}:${devConfig.port}`
            ]
          },
          //编译出错!
          onErrors: function(severity, errors) {
            if (severity !== "error") {
              return;
            }
            const error = errors[0];
            const filename = error.file.split("!").pop();
            //编译出错时,右下角弹出错误提示!
            notifier.notify({
              title: "xc-cli",
              message: severity + ": " + error.name,
              subtitle: filename || "",
              icon: path.join(__dirname, "xc-cli.png")
            });
          }
        })
      ]
    });
    module.exports = devConf;
    

    8.3 通过创建以上文件,并下载相应的依赖和创建项目入口,我们就可以通过npm run dev在本地开发vue项目啦!!!

    9.创建 build/webpack.prod.conf.js

    9.1 此文件主要用于构建生产环境的配置.
    9.2

    "use strict";
    //引入node path路径模块
    const path = require("path");
    //引入webpack
    const webpack = require("webpack");
    //一个webpack配置合并模块,可简单的理解为与Object.assign()功能类似!
    const merge = require("webpack-merge");
    //引入webpack生产环境配置参数
    const prodConfig = require("../config").build;
    //引入webpack基本配置
    const baseConf = require("./webpack.base.conf");
    //一个创建html入口文件的webpack插件!
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    //一个抽离出css的webpack插件!
    const ExtractTextPlugin = require("extract-text-webpack-plugin");
    //一个压缩css的webpack插件!
    const OptimizeCSSPlugin = require("optimize-css-assets-webpack-plugin");
    //一个拷贝文件的webpack插件!
    const CopyWebpackPlugin = require("copy-webpack-plugin");
    
    //资源路径
    function assetsPath(_path) {
      return path.join(prodConfig.staticPath, _path);
    }
    //将webpack基本配置与生产环境配置合并!
    const prodConf = merge(baseConf, {
      //项目出口配置
      output: {
        //Build后所有文件存放的位置
        path: path.resolve(__dirname, "../public"),
        //html引用资源路径,可在此配置cdn引用地址!
        publicPath: prodConfig.publicPath,
        //文件名
        filename: assetsPath("js/[name].[chunkhash].js"),
        //用于打包require.ensure(代码分割)方法中引入的模块
        chunkFilename: assetsPath("js/[name].[chunkhash].js")
      },
      //生成sourceMaps(方便调试)
      devtool: prodConfig.devtoolType,
      module: {
        //处理模块的规则(可在此处使用不同的loader来处理模块!)
        rules: [
          //使用vue-loader处理以vue结尾的文件!
          {
            test: /.vue$/,
            loader: "vue-loader",
            options: prodConfig.vueloaderConf
          },
          {
            test: /.css$/,
            use: ExtractTextPlugin.extract({
              use: ["css-loader", "postcss-loader"],
              fallback: "vue-style-loader"
            })
          },
          {
            test: /.less$/,
            use: ExtractTextPlugin.extract({
              use: ["css-loader", "less-loader", "postcss-loader"],
              fallback: "vue-style-loader"
            })
          }
        ]
      },
      plugins: [
        //每个chunk头部添加hey,xc-cli!
        new webpack.BannerPlugin("hey,xc-cli"),
    
        //压缩js
        new webpack.optimize.UglifyJsPlugin({
          parallel: true,
          compress: {
            warnings: false
          }
        }),
    
        //分离入口引用的css,不内嵌到js bundle中!
    
        new ExtractTextPlugin({
          filename: assetsPath("css/[name].[contenthash].css"),
          allChunks: false
        }),
    
        //压缩css
        new OptimizeCSSPlugin(),
    
        //根据模块相对路径生成四位数hash值作为模块id
        new webpack.HashedModuleIdsPlugin(),
    
        //作用域提升,提升代码在浏览器执行速度
        new webpack.optimize.ModuleConcatenationPlugin(),
    
        //抽离公共模块,合成一个chunk,在最开始加载一次,便缓存使用,用于提升速度!
    
        // 1. 第三方库chunk
        new webpack.optimize.CommonsChunkPlugin({
          name: "vendor",
          minChunks: function(module) {
            //在node_modules的js文件!
            return (
              module.resource &&
              /.js$/.test(module.resource) &&
              module.resource.indexOf(path.join(__dirname, "../node_modules")) === 0
            );
          }
        }),
    
        // 2. 缓存chunk
        new webpack.optimize.CommonsChunkPlugin({
          name: "manifest",
          minChunks: Infinity
        }),
        // 3.异步 公共chunk
        new webpack.optimize.CommonsChunkPlugin({
          name: "app",
          children: true,
          // (选择所有被选 chunks 的子 chunks)
          async: true,
          // (创建一个异步 公共chunk)
          minChunks: 3
          // (在提取之前需要至少三个子 chunk 共享这个模块)
        }),
    
        //将整个文件复制到构建输出指定目录下
        new CopyWebpackPlugin([
          {
            from: path.resolve(__dirname, "../static"),
            to: prodConfig.staticPath,
            ignore: [".*"]
          }
        ]),
    
        //生成html
        new HtmlWebpackPlugin({
          filename: path.resolve(__dirname, "../public/index.html"),
          template: "index.html",
          favicon: path.resolve(__dirname, "../favicon.ico"),
          //js资源插入位置,true表示插入到body元素底部
          inject: true,
          //压缩配置
          minify: {
            //删除Html注释
            removeComments: true,
            //去除空格
            collapseWhitespace: true,
            //去除属性引号
            removeAttributeQuotes: true
          },
          //根据依赖引入chunk
          chunksSortMode: "dependency"
        })
      ]
    });
    module.exports = prodConf;
    

    10. 创建 build/build.js

    10.1 此文件是项目打包服务,用来构建一个全量压缩包
    10.2

    "use strict";
    //node for loading
    const ora = require("ora");
    // rm-rf for node
    const rm = require("rimraf");
    //console for node
    const chalk = require("chalk");
    //path for node
    const path = require("path");
    //webpack
    const webpack = require("webpack");
    //webpack production setting
    const config = require("./webpack.prod.conf");
    //指定删除的文件
    const rmFile = path.resolve(__dirname, "../public/static");
    //build start loading
    const spinner = ora("building for production...");
    spinner.start();
    
    //构建全量压缩包!
    rm(rmFile, function(err) {
      if (err) throw err;
      webpack(config, function(err, stats) {
        spinner.stop();
        if (err) throw err;
        process.stdout.write(
          stats.toString({
            colors: true,
            modules: false,
            children: false,
            chunks: false,
            chunkModules: false
          }) + "
    
    "
        );
    
        if (stats.hasErrors()) {
          console.log(chalk.red("  Build failed with errors.
    "));
          process.exit(1);
        }
    
        console.log(chalk.cyan("  Build complete.
    "));
        console.log(
          chalk.yellow(
            "  Tip: built files are meant to be served over an HTTP server.
    " +
              "  Opening index.html over file:// won't work.
    "
          )
        );
      });
    });
    

    10.3 创建好以上文件 我们就可以通过npm run build来打包我们的项目文件并部署上线啦。

    11.大功告成!

    通过以上步骤,一个spa版的vue脚手架就大功告成啦!

    如果对一些细节不懂的可以留言或者上我的github查看

    https://github.com/webfansplz...

  • 相关阅读:
    Eureka 原理圖
    RabbitMQ 介紹
    rabbitmq-3.5.1-安裝
    MyBatis 基础入门
    CSS
    程序员必会算法-KMP算法
    编程这些年
    排序算法之直接插入排序
    排序算法之选择排序
    排序算法之冒泡排序
  • 原文地址:https://www.cnblogs.com/gluncle/p/8608723.html
Copyright © 2020-2023  润新知