天天看點

vue-cli3 适配移動端rem

  1. 使用vue-cli
npm install -g @vue/cli // 使用vue-cli3版本
  1. 自定義功能配置
  • TypeScript
  • TypeScript
  • Progressive Web App (PWA) Support
  • Router
  • Vuex
  • CSS Pre-processors
  • Linter / Formatter
  • Unit Testing
  • E2E Testing
  1. 建立項目
vue create demo
  1. 選擇Manually select features // 自定義功能配置
    vue-cli3 适配移動端rem
  2. 選擇自定義功能配置

    Babel編譯、使用Vue路由、Vue狀态管理器、CSS預處理器、代碼檢測和格式化、以及單元測試

    vue-cli3 适配移動端rem
  3. 選擇css預處理器,具體看選擇技術棧
    vue-cli3 适配移動端rem
  4. 選擇ESLint的代碼規範
    vue-cli3 适配移動端rem
  5. 進行代碼檢測,選擇在儲存時進行檢測
    vue-cli3 适配移動端rem
  6. 選擇單元測試解決方案,此處選擇jest
    vue-cli3 适配移動端rem
  7. 選擇Babel、PostCSS、ESLint等配置檔案存放位置

    推薦單獨儲存在各自的配置檔案

    vue-cli3 适配移動端rem
? save this as a preset for future projects? Yes
//是否将以上這些将此儲存為未來項目的預配置嗎?
? save preset as:vue-test
//描述項目 
           
  1. 配置完成後等待vue-cli3完成初始化,使用指令
vue ui
vue-cli3 适配移動端rem
  1. vue.config.js
在根目錄下建立一個vue.config.js檔案,進行自定義配置
'use strict';
const path = require('path');

function resolve(dir) {
  return path.join(__dirname, dir);
}

const name = 'wechat demo'; // page title
const mockPort = 3000; // mock server port

module.exports = {
  // 修改預設的入口
  pages: {
    index: {
      entry: 'src/main.js',
      template: 'public/index.html',
      filename: 'index.html'
    }
  },
  lintOnSave: true, // 關閉eslint規範
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
      'Access-Control-Allow-Headers':
        'X-Requested-With, content-type, Authorization'
    },
    open: true,
    hot: true,
    overlay: {
      warnings: false,
      errors: true
    },
    proxy: {
      [process.env.VUE_APP_BASE_API]: {
        changeOrigin: true, //開啟代理:在本地會建立一個虛拟服務端,然後發送請求的資料,并同時接收請求的資料,這樣服務端和服務端進行資料的互動就不會有跨域問題
        target: `http://localhost:${mockPort}`,
        ws: true, // 是否啟用websocket
        pathRewrite: {
          ['^' + process.env.VUE_APP_BASE_API]: ''
        }
      }
    }
  },
  filenameHashing: true,
  css: {
    loaderOptions: {
      css: {},
      // sass: {
      //   data: '@import "@styles/skin.scss"'
      // },
      postcss: {
        plugins: [
          require('postcss-px2rem')({
            remUnit: 75,
            propList: ['*'],
            mediaQuery: false, // 允許在媒體查詢中轉換px。
            exclude: '/node_modules/',
            minPixelValue: 3, //設定要替換的最小像素值(3px會被轉rem)。 預設 0
            selectorBlackList: ['weui', 'mu'] // 忽略轉換正則比對項
          })
        ]
      }
    }
  },
  configureWebpack: {
    // provide the app's title in webpack's name field, so that
    // it can be accessed in index.html to inject the correct title.
    name: name,
    resolve: {
      alias: {
        '@': resolve('src'),
        '~': resolve('packages')
      }
    }
  },
  chainWebpack(config) {
    config.plugins.delete('preload'); // TODO: need test
    config.plugins.delete('prefetch'); // TODO: need test

    // set svg-sprite-loader
    config.module
      .rule('svg')
      .exclude.add(resolve('src/icons'))
      .end();
    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add(resolve('src/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })
      .end();

    // lib目錄是元件庫最終打包好存放的地方,不需要eslint檢查
    // src/docs是存放md文檔的地方,也不需要eslint檢查
    config.module
      .rule('eslint')
      .exclude.add(path.resolve('lib'))
      .end()
      .exclude.add(path.resolve('src/docs'))
      .end();
    // packages和src目錄需要加入編譯
    config.module
      .rule('js')
      .include.add(/packages/)
      .end()
      .include.add(/src/)
      .end()
      .use('babel')
      .loader('babel-loader')
      .tap(options => {
        // 修改它的選項...
        return options;
      });

    config.module
      .rule('images')
      .test(/\.(png|jpg|gif)$/)
      .use('url-loader')
      .loader('url-loader')
      .options({
        name: 'images/[name].[ext]',
        limit: 1000
      })
      .end();

    // set preserveWhitespace
    config.module
      .rule('vue')
      .use('vue-loader')
      .loader('vue-loader')
      .tap(options => {
        options.compilerOptions.preserveWhitespace = true;
        return options;
      })
      .end();

    config
      // https://webpack.js.org/configuration/devtool/#development
      .when(process.env.NODE_ENV === 'development', config =>
        config.devtool('cheap-source-map')
      );

    config.when(process.env.NODE_ENV !== 'development', config => {
      config
        .plugin('ScriptExtHtmlWebpackPlugin')
        .after('html')
        .use('script-ext-html-webpack-plugin', [
          {
            // `runtime` must same as runtimeChunk name. default is `runtime`
            inline: /runtime\..*\.js$/
          }
        ])
        .end();
      config.optimization.splitChunks({
        chunks: 'all',
        cacheGroups: {
          libs: {
            name: 'chunk-libs',
            test: /[\\/]node_modules[\\/]/,
            priority: 10,
            chunks: 'initial' // only package third parties that are initially dependent
          },
          elementUI: {
            name: 'chunk-elementUI', // split elementUI into a single package
            priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
            test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
          },
          commons: {
            name: 'chunk-commons',
            test: resolve('src/components'), // can customize your rules
            minChunks: 3, //  minimum common number
            priority: 5,
            reuseExistingChunk: true
          }
        }
      });
      config.optimization.runtimeChunk('single');
    });
  }
};

           
  1. 适配移動端
  • 使用終端指令

cnpm i lib-flexible – save

cnpm i postcss-px2rem --save

使用postcss-px2rem在移動端使用第三vant庫時,字型樣式會縮小,vant是以37.5進行适配。

解決方案:

cnpm uninstall postcss-px2rem --save

cnpm i postcss-px2rem-exclude --save

在postcss.config.js中增加配置

module.exports = {
  plugins: {
    autoprefixer: {},
    'postcss-px2rem-exclude': {
      remUnit: 72,
      exclude: /node_modules|folder_name/i
    }
  }
};
           
1px的邊框容易缺失,使用 /no/ 文法來屏蔽該屬性轉換

遇到的坑:

  1. 插件會轉化所有的樣式的px。比如引入了第三方UI,也會被轉化。使用selectorBlackList字段,來過濾。實際上還是會存在這個問題
  2. 不想px被轉化成rem,可以簡單的使用大寫PX或者是Px;