requirejs项目完整迁移webpack

迁移原因

某些项目由于种种原因,之前采用的requirejs框架开发,由于其所有资源都是通过xhr请求获取,会导致用户等待时间过长等性能问题,又由于项目整体重构采用脚手架成本过大,风险过高,于是需自定义webpack配置,进行整体打包,这样再首次加载系统的时候代码体量会增大,但后续所有的请求都无需通过xhr,再一定程度上可提高用户体验

可行性分析

requirejs项目采用的AMD规范,而webpack也支持这种模块语法,这样webpack就能够动态分析项目中的依赖项,这是项目迁移成功的关键所在。

requirejs项目特点

  1. 使用amd语法
  2. js依赖直接写依赖地址
  3. html文本类依赖使用 text! 前缀引用
  4. css依赖使用css!前缀引用

迁移目标

  1. 不改变项目原有代码结构
  2. 所有依赖全部成功打包
  3. 引入vue文件解析
  4. vue文件与老代码格式共存

解决方案

  1. 编写js脚本,将所有text! css! 依赖加载前缀去除
  2. 配置webpack 中对应的loader,并增加vue-loader
  3. 对requirejs中的配置内容映射为webpack中的 alias,以解决路径解析问题
  4. 删除引入requirejs的script

配置文件

采用webpack4的配置文件如下,仅供参考

const path = require('path'),
    WebpackNotifierPlugin = require('webpack-notifier'),
    HtmlWebpackPlugin = require('html-webpack-plugin'),
    CopyWebpackPlugin = require('copy-webpack-plugin'),
    {VueLoaderPlugin} = require('vue-loader'),
    MiniCssExtractPlugin = require("mini-css-extract-plugin");
const webpack = require('webpack');
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
let base = {
  index: './main.js'
}
const SRCPATH = "src";
const isDev = process.env.NODE_ENV !== 'production';
let desPath = "./";
let proxyTarget = "";
let copyFiles = ['default.conf'].map((el)=>{
	return {
      // 从public中复制文件
      from: path.resolve(__dirname, el),
      // 把复制的文件存放到dis里面
      to: path.resolve(desPath, 'dist')
    }
})
module.exports = {
  devtool: isDev ? 'source-map' : "eval", //配合 target 用来生成source-map 文件,以便 开发调试 debug 等, devtool 意指 开发工具
  target: 'web',
  entry: base,
  devServer: {
    // port: 8080,
    static: path.resolve(desPath, '/dist'),
    hot: true,
    proxy: {
      '/api': {
        target: proxyTarget,
        // secure: false,  // 如果是https接口,需要配置这个参数
        ws: true,
        changeOrigin: true, // 是否跨域
        pathRewrite: {
          '^/api': '', // 重写接口
        }
      },
    },
  },
  output: { //指定输出目录,和文件名
    path: path.resolve(desPath, 'dist'),
    filename: '[name]_[contenthash].js',
    assetModuleFilename: 'assets/[name]_[contenthash][ext][query]',
    clean: true
  },
  optimization: {
    minimizer: [
      `...`,
      new CssMinimizerPlugin(),
    ],
  },
  externals: {
    Vue: 'Vue',
    Vuex: 'Vuex',
    'vue-router': 'VueRouter',
    echarts: 'echarts',
    moment: 'moment',
    'element-ui': 'ELEMENT',
    vuedraggable: 'vuedraggable',
    vant: 'vant'
  },
  resolve: { //resolve字段最常用的就是 alias (别名)属性,用来把一些冗长的路径替换为简单的字符,以便js中引入模块时更简洁
    extensions: ['.js', '.vue', '.css', '.html', '...'],
    alias: {
      '@':path.resolve(__dirname, './mini'),
      gotop: path.resolve(__dirname, 'src/js/com/gotop.js'),
      carousel: path.resolve(__dirname, 'src/js/com/carousel.js'),
      waterfall: path.resolve(__dirname, 'src/js/com/waterfall.js'),
      biz: path.resolve(__dirname, './mini/js/biz'),
      dao: path.resolve(__dirname, './mini/js/dao'),
      common: path.resolve(__dirname, './mini/js/common'),
      template: path.resolve(__dirname, './mini/js/template'),
      widget: path.resolve(__dirname, './mini/js/widget'),
      text: path.resolve(__dirname, './mini/js/lib/text'),
      css: path.resolve(__dirname, './mini/js/lib/css'),
      store: path.resolve(__dirname, './mini/js/common/store'),
      config: path.resolve(__dirname, './mini/js/common/config'),
      util: path.resolve(__dirname, './mini/js/common/util'),
      Util: path.resolve(__dirname, './mini/js/common/util'),
      constance: path.resolve(__dirname, './mini/js/common/constance'),
      listmix: path.resolve(__dirname, './mini/js/common/listmix'),
      treemix: path.resolve(__dirname, './mini/js/common/treemix'),
      formmix: path.resolve(__dirname, './mini/js/common/formmix'),
      workflowmix: path.resolve(__dirname, './mini/js/common/workflowmix'),
      routermap: path.resolve(__dirname, './mini/js/common/routermap'),
    }
  },
  resolveLoader: {
    alias: {
      "text": "raw-loader",
      "css": ["style-loader", "css-loader"]
    }
  },
  plugins: [
    new webpack.optimize.LimitChunkCountPlugin({
      maxChunks: 1,
    }),
    new VueLoaderPlugin(),
    new MiniCssExtractPlugin(),
    new WebpackNotifierPlugin({
      title: 'Webpack 编译成功',
      alwaysNotify: false,
      onlyOnError: true
    }), new HtmlWebpackPlugin({
      template: "./mini/index.html", // 要打包输出哪个文件,可以使用相对路径
      filename: "index.html" // 打包输出后该html文件的名称
    }),
    new CopyWebpackPlugin({
      patterns: [
        {
          // 从public中复制文件
          from: path.resolve(__dirname, 'mini/lib'),
          // 把复制的文件存放到dis里面
          to: path.resolve(desPath, 'dist/lib')
        },
        {
          // 从public中复制文件
          from: path.resolve(__dirname, 'mini/config.js'),
          // 把复制的文件存放到dis里面
          to: path.resolve(desPath, 'dist')
        },
        {
          // 从public中复制文件
          from: path.resolve(__dirname, 'mini/css'),
          // 把复制的文件存放到dis里面
          to: path.resolve(desPath, 'dist/css')
        }
      ].concat(copyFiles),
    })
  ],
  module: {
    unknownContextCritical: false,
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        include: path.resolve(__dirname, SRCPATH),
      },
      {
        test: /\.m?js$/,
        exclude: /(node_modules)|(lib)/,
        include: path.resolve(__dirname, SRCPATH+"/js"),
        use: [{
          loader: 'babel-loader'
        }]
      },
      {
        test: /\.(css)|(less)$/i,
        include: path.resolve(__dirname, SRCPATH),
        // 'vue-style-loader',
        use: [MiniCssExtractPlugin.loader, {
          loader: "css-loader"
        }, 'less-loader']
      },
      {
        test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i,
        include: path.resolve(__dirname, SRCPATH),
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 20 * 1024 // 16kb 64k
          }
        }
        // use: [
        //     {
        //       loader: 'url-loader',
        //       options: {
        //         esModule: true,
        //         limit: 8196 * 2,
        //         name: "[name]_[contenthash:6].[ext]",
        //         // generator: (content, mimetype, encoding, resourcePath) => {
        //         //   return `data:${mimetype}${
        //         //     encoding ? `;${encoding}` : ''
        //         //   },${content.toString(encoding)}`;
        //         // },
        //       },
        //     },
        //   ],
      },
      {
        test: /\.html$/i,
        include: path.resolve(__dirname, SRCPATH),
        use: [
          {
            loader: 'raw-loader',
            options: {
              esModule: false,
            },
          },
        ]
      },
      // {
      //   test: /\.(png|jpg|gif)$/i,
      //   use: [
      //     {
      //       loader: 'url-loader',
      //       options: {
      //         esModule: false,
      //         limit: 8196 * 2,
      //         name: "img/[name]_[contenthash:6].[ext]",
      //       },
      //     },
      //   ],
      // },
    ],
  }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值