Recently, due to business needs, a NEW H5 project for VUE was started over

I always like to use newer versions of things, so vuE-CLI4, Webpack5, Typescript!!

Why not use Vue3, because I personally feel that the 3.x version is not suitable for production at present [I will never admit that it is because I can’t learn Vue3….]

My expectations for this project are as follows:

  1. Use vuE-CLI4 / Webpack5 to build the project
  2. Introducing the Typescript
  3. The introduction of Eslint
  4. Use gzip/image compression, etc
  5. Adaptive layout amFE-Flexible/PostCSS-pxtorem
  6. Import the Ant-UI and configure the import on demand

So! Let’s get down to business.

Initialize the project

Install the Vue – cli4

First we need to use the vue -v command line to check whether the local machine has vuE-CLI installed, or whether the vue-CLI version is 4.x

If it’s already installed, but the version is too low, delete it and reinstall it

npm uninstall vue-cli -g
Copy the code

Then again,

npm install @vue/cli -g 
Copy the code

After the installation is complete, run the vue -v command again to check the version. If the 4.x version is installed, you can continue the following operations.

Initialize the project

Vue create # Your project name #Copy the code

Use vue’s create command to build the project, such as vue create my-app

Next comes the option to customize the configuration

First here we choose the third: Manually select features

Then check the module you need, I check is:

Babel / TypeScript / Router / Vuex / CSS Pre-processors / Lint

Copy the code

As is shown in the picture above ~

The next step is to let you choose which version of Vue you want to use.

Then choose the routing mode. The reason for not choosing the History mode is that it is too troublesome to find the back-end configuration, so it is better to do it yourself

Last question: whether to keep this configuration, so that the next initialization of the project can be directly used, I chose not (after all, the next new project is estimated to have a new thing ~~~

Ok, so we are ready to initialize

When the project is running, you will see the familiar welcome page ~

Depend on the installation

Since vue-CLI 3.x and Webpack 4.x, there are no more configuration files, but a vue.config.js file instead

Due to the need to add pXtorem configuration and the introduction of vant components on demand, as well as various compression plug-ins, I will present the final configuration file directly below:

First we need to install various dependencies:

// NPM install postcss-pxtorem -d NPM install amfe-flexible // CNPM install image-webpack-loader --save-dev cnpm install pngquant-bin --save-dev npm install imagemin-gifsicle --save-dev npm install imagemin-mozjpeg --save-dev npm install imagemin-optipng --save-dev npm install imagemin-pngquant --save-dev npm install Compression webpack-plugin --save-dev // note that image-webpack-loader and pngquant-bin must be installed using CNPM. Using NPM causes the project to fail to run // install vant UI and its on-demand import plugin NPM I ant -s // This is the on-demand import plugin NPM I ts-import-plugin --save-devCopy the code

Now that the dependencies are installed, it’s time to configure the file:

Configuration file

vue.config.js

vue.config.js

// vue.config.js
const path = require('path');
const CompressionWebpackPlugin = require('compression-webpack-plugin'); // Enable gzip compression, reference as needed
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\? . *)? $/i; // Enable gzip compression and write as needed
const merge = require('webpack-merge');
const tsImportPluginFactory = require('ts-import-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
  .BundleAnalyzerPlugin; // Package analysis
const IS_PROD = ['production'.'prod'].includes(process.env.NODE_ENV);
const resolve = dir= > path.join(__dirname, dir);
module.exports = {
  publicPath: process.env.NODE_ENV === 'production' ? '/site/vue-demo/' : '/'.// Public path
  indexPath: 'index.html'.// The path relative to the package path index.html
  outputDir: process.env.outputDir || 'dist'.// 'dist', directory for production build files
  assetsDir: 'static'.Static resources (JS, CSS, img, fonts) directory relative to outputDir
  lintOnSave: false.// Whether to use eslint-loader in the development environment to save lint code each time
  runtimeCompiler: true.// Whether to use the Vue build with the runtime compiler
  productionSourceMap: !IS_PROD,
  // Source map for production environment
  // parallel: require('os').cpus().length > 1,
  parallel: false.// Whether thread-loader is used for Babel or TypeScript. This option is automatically enabled when the system CPU has more than one kernel and only applies to production builds.
  pwa: {},
  chainWebpack: config= > {
    config.resolve.symlinks(true); // Fix hot update failure
    // If you are using multi-page packaging, use vue inspect --plugins to see if the HTML is in the result array
    config.plugin('html').tap(args= > {
      // Fix Lazy loading routes Error
      args[0].chunksSortMode = 'none';
      return args;
    });
    config.resolve.alias // Add an alias
      .set(The '@', resolve('src'))
      .set('@assets', resolve('src/assets'))
      .set('@components', resolve('src/components'))
      .set('@views', resolve('src/views'))
      .set('@store', resolve('src/store'));
    // Compress the image
    // need NPM I -d image-webpack-loader
    config.module
      .rule('images')
      .use('image-webpack-loader')
      .loader('image-webpack-loader')
      .options({
        bypassOnDebug: true
      }).end();
    config.module
      .rule('ts')
      .use('ts-loader')
      .tap(options= > {
        options = merge(options, {
          happyPackMode: true.transpileOnly: true.getCustomTransformers: () = > ({
            before: [
              tsImportPluginFactory({
                libraryName: 'vant'.libraryDirectory: 'es'.// This sentence must be added, otherwise there is no effect to modify the theme
                style: name= > `${name}/style/less`}})]),compilerOptions: {
            module: 'es2015'}})return options
      });
    // Package analysis, after the package automatically generates a file named report.html (can be ignored)
    if (IS_PROD) {
      config.plugin('webpack-report').use(BundleAnalyzerPlugin, [{
        analyzerMode: 'static'}]); }},configureWebpack: config= > {
    // Enable gzip compression
    // NPM I -d compression-webpack-plugin is required
    const plugins = [];
    if (IS_PROD) {
      plugins.push(
        new CompressionWebpackPlugin({
          filename: '[path].gz[query]'.algorithm: 'gzip'.test: productionGzipExtensions,
          threshold: 10240.minRatio: 0.8})); } config.plugins = [...config.plugins, ...plugins]; },css: {
    extract: IS_PROD,
    requireModuleExtension: true.// If it is false, the vant styles imported on demand may not take effect
    loaderOptions: {
      less: {
        // 'globalVars' defines global objects that can be added to global variables
        globalVars: {
          primary: '# 333'}},postcss: {
        plugins: [
          require('autoprefixer') ({// Configure to use autoprefixer
            overrideBrowserslist: ['last 15 versions']}),// If some place does not want to convert px. You can simply use uppercase PX or PX.
          require('postcss-pxtorem') ({rootValue: 37.5.// The base of conversion
            propList: [The '*'].//exclude: /node_modules/ // No conversion is required})]}}},devServer: {
    overlay: {
      // Make the browser overlay display both warnings and errors
      warnings: true.errors: true
    },
    host: 'localhost'.port: 8080./ / the port number
    https: false.// https:{type:Boolean}
    open: false.// Configure automatic browser startup
    hotOnly: true./ / hot update
    proxy: {
      // Configure multiple cross-domains
      // '/api': {
      // target: 'http://xxx.xxx',
      // changeOrigin: true,
      // // ws: true,// Websocket support
      // secure: false,
      // pathRewrite: {
      // '^/api': '/'
      / /}
      // },}}};Copy the code

Each field configuration is explained accordingly. If there is a dependency missing, install it again

tsconfig.json

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext"."module": "esnext"."strict": true."jsx": "preserve"."importHelpers": true."moduleResolution": "node"."experimentalDecorators": true."skipLibCheck": true."esModuleInterop": true."allowSyntheticDefaultImports": true."sourceMap": true."baseUrl": "."."types": [
      "webpack-env"]."paths": {
      "@ / *": [
        "src/*"]},"lib": [
      "esnext"."dom"."dom.iterable"."scripthost"]},"include": [
    "src/**/*.ts"."src/**/*.tsx"."src/**/*.vue"."tests/**/*.ts"."tests/**/*.tsx"]."exclude": [
    "node_modules"]}Copy the code

babel.config.js

babel.config.js

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'].plugins: [['import', {
      libraryName: 'vant'.libraryDirectory: 'es'.style: true
    }, 'vant']]}Copy the code

main.ts

main.ts

import Vue from 'vue'; import App from './App.vue'; import router from './router'; import store from './store'; import 'amfe-flexible/index.js'; // Flex layout vue.config. productionTip = false; new Vue({ router, store, render: (h) => h(App), }).$mount('#app');Copy the code

That’s almost done!!

My project structure and package.json are shown below:

In this way, a project is basically set up. If you encounter any problems in the middle of the process, please comment and discuss with us