- 使用vue-cli
npm install -g @vue/cli // 使用vue-cli3版本
- 自定義功能配置
- TypeScript
- TypeScript
- Progressive Web App (PWA) Support
- Router
- Vuex
- CSS Pre-processors
- Linter / Formatter
- Unit Testing
- E2E Testing
- 建立項目
vue create demo
- 選擇Manually select features // 自定義功能配置
vue-cli3 适配移動端rem -
選擇自定義功能配置
Babel編譯、使用Vue路由、Vue狀态管理器、CSS預處理器、代碼檢測和格式化、以及單元測試
vue-cli3 适配移動端rem - 選擇css預處理器,具體看選擇技術棧
vue-cli3 适配移動端rem - 選擇ESLint的代碼規範
vue-cli3 适配移動端rem - 進行代碼檢測,選擇在儲存時進行檢測
vue-cli3 适配移動端rem - 選擇單元測試解決方案,此處選擇jest
vue-cli3 适配移動端rem -
選擇Babel、PostCSS、ESLint等配置檔案存放位置
推薦單獨儲存在各自的配置檔案
vue-cli3 适配移動端rem
? save this as a preset for future projects? Yes
//是否将以上這些将此儲存為未來項目的預配置嗎?
? save preset as:vue-test
//描述項目
- 配置完成後等待vue-cli3完成初始化,使用指令
vue ui![]()
vue-cli3 适配移動端rem
- 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');
});
}
};
- 适配移動端
- 使用終端指令
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/ 文法來屏蔽該屬性轉換
遇到的坑:
- 插件會轉化所有的樣式的px。比如引入了第三方UI,也會被轉化。使用selectorBlackList字段,來過濾。實際上還是會存在這個問題
- 不想px被轉化成rem,可以簡單的使用大寫PX或者是Px;