从零搭建webpack5+vue3+TS+SCSS项目

发布于:2024-05-02 ⋅ 阅读:(21) ⋅ 点赞:(0)

webpack项目基础配置

  • webpack版本
   webpack-cli: 5.1.4
   webpack: 5.91.0
  • 新建项目文件夹ts-animates-webpack-demo
  • pnpm初始化 pnpm init,根目录下生成package.json文件
{
  "name": "ts-animates-webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
}

  • 新建src/dist目录
  • 全局安装过webpack、webpack-cli
  • 根目录下新建webpack配置文件webpack.config.js
const path = require('path')

module.exports = {
    entry: './src/index.ts',
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')
    },
    mode: 'development',
}

webpack处理ts

  • 安装typescript、ts-loader
  • 添加webpack配置
module: {
        rules: [
            {
                test: /\.(ts)$/,
                loader: 'ts-loader'
            }
        ]
    }
  • 添加tsconfig.json配置文件
{
    "compilerOptions": {
        "sourceMap": true
    },
    "include": [
        "src/**/*"
    ],
    "exclude": [
        "node_modules"
    ]
}
  • 在src目录下创建index.ts文件
  • 执行pnpm run dev,dist文件夹下生成main.js文件,内容如下:

/******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ "./src/index.ts":
 (() => {

eval("var num = 1;\nconsole.log(num);\n\n\n//# sourceURL=webpack://ts-animates-webpack-demo/./src/index.ts?");

/***/ })

/******/ 	});

/******/ 	var __webpack_exports__ = {};
/******/ 	__webpack_modules__["./src/index.ts"]();
/******/ 	
/******/ })()
;

webpack处理图片

  • 官方文档介绍
  • webpack5 无需安装loader,直接配置规则如下:
 module: {
        rules: [
            {
                test: /\.png/,
                type: 'asset/resource'
            }
        ]
    }
  • 默认会将图片输出到dist目录下,可在output——assetModuleFilename中配置如下内容,可将图片打包到dist/images文件夹下
output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist'),
        assetModuleFilename: 'images/[hash][ext][query]'
    },

webpack处理vue

  • 安装vue、vue-loader
  • webpack配置模块规则
module: {
        rules: [
            {
                test: /\.vue/,
                loader: 'vue-loader'
            }
        ]
    },
  • 在入口index.ts文件中创建app实例并挂载
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)
app.mount('#app')

报错:“找不到模块./App.vue或其相应的类型声明:”

解决方案如下:

  1. 在根目录创建vue.d.ts声明文件
declare module "*.vue" {
    import { defineComponent } from 'vue'
    const Component: ReturnType<typeof defineComponent>
    export default Component
}
  1. 在tsconfig.json配置文件中加入vue.d.ts
 "include": [
        "src/**/*","vue.d.ts"
    ],

报错:export 'render' (imported as 'render') was not found

export 'render' (imported as 'render') was not found in './App.vue?vue&type=template&id=7ba5bd90&ts=true' (possible exports: __esModule) @ ./src/index.ts 4:16-36

解决方案:ts-loader规则增加options配置如下:

vue 单文件组件中假如使用了 lang="ts", ts-loader需要配置 appendTsSuffixTo: [/.vue$/],用来给 .vue文件添加个 .ts后缀用于编译。

module: {
        rules: [
            {
                test: /\.(ts)$/,
                loader: 'ts-loader',
                options: {
                    configFile: path.resolve(process.cwd(), 'tsconfig.json'),
                    appendTsSuffixTo: [/\.vue$/]
                 },
            },
        ]
     }

报错:TS2307: Cannot find module './assets/11.jpg' or its corresponding type declarations.

解决方案:在根目录下新增images.d.ts配置文件

declare module '*.jpg' {
    const value: string
    export default value
}

tsconfig.json文件修改如下:

 "include": [
        "src/**/*","*.d.ts"
    ],

问题:图片展示失败

image.png

image.png

__webpack_require__加载的图片返回的结果没有default属性

解决方案:修改tsconfig.js配置文件

 "compilerOptions": {
      "sourceMap": true,
       "module": "ES6",
       "moduleResolution": "Node"
    },

target

指定模块解析策略:

  • Default:

    Classic if  is AMDUMDSystem, or ES6/ES2015; Matches if  is node16 or nodenextNode otherwise.

  • Allowed:

    • classic
    • node10/node
    • node16
    • nodenext
    • bundler

默认是ES3

  • es3
  • es5
  • es6/es2015
  • es2016
  • es2017
  • es2018
  • es2019
  • es2020
  • es2021
  • es2022
  • esnext

module

  • Default:

    CommonJS if  is ES3 or ES5ES6/ES2015 otherwise.

  • Allowed:

    • none
    • commonjs
    • amd
    • umd
    • system
    • es6/es2015
    • es2020
    • es2022
    • esnext
    • node16
    • nodenext
    • preserve

module为commonjs时的转换结果:

b.js

export let getTime = new Date()

export default function add(a, b) {
    return a + b
}

index.js

import b from './b'
console.log(b)

commonJS时的转换结果:

        "./src/example/modules/b.js": 
        ((__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{

            "use strict";
            __webpack_require__.r(__webpack_exports__);
            /* harmony export */
            __webpack_require__.d(__webpack_exports__, {
                /* harmony export */
                "default": ()=>(/* binding */
                add),
                /* harmony export */
                getTime: ()=>(/* binding */
                getTime)/* harmony export */
            });
            let getTime = new Date()

            function add(a, b) {
                return a + b
            }

            /***/
        }
        ),

        /***/
        "./src/example/modules/index.js": 
        ((__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{

            "use strict";
            __webpack_require__.r(__webpack_exports__);
            /* harmony import */
            var _b__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./b */
            "./src/example/modules/b.js");
           
            console.log(_b__WEBPACK_IMPORTED_MODULE_0__["default"])

            /***/
        }
        )
        /******/
    });

moduleResolution

模块解析; 应该从什么位置寻找模块

  • classic 经典
  • node 和node解析模块一致(唯一的变化,是将js替换为ts)

webpack处理css文件

  • 安装style-loader、css-loader
  • 配置module-rules
{
     test: /\.css/,
     use: ['style-loader', 'css-loader']
}

html-webpack-plugin插件指定index.html

  • 安装html-webpack-plugin
  • 在webpack.config.js文件中配置该插件
const HtmlWebpackPlugin = require('html-webpack-plugin')

 plugins: [
        new HtmlWebpackPlugin({
            template: './index.html'
        })
    ]
  • 根目录下新增index.html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
    </div>
</body>
</html>

webpack-dev-server

  • 安装webpack-dev-server
  • package.json文件中的script修改如下
 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server"
  },

加入vue-router

  • 安装vue-router
  • src目录下新建router文件夹,再建index.ts文件, 内容如下:
import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '../pages/home.vue'
import CssFlex from '../pages/CssFlex.vue'
const routes = [
    {
        path: '/',
        component:  Home
    },
    {
        path: '/css/flex',
        component: CssFlex

    }
]


const router = createRouter({
    history: createWebHashHistory(),
    routes,
})

export default router
  • src目录下的index.ts文件,内容修改如下:
import { createApp } from 'vue'
import App from './App.vue'
import Router from './router/index'


const app = createApp(App)

app.use(Router)
app.mount('#app')

报错:Module not found: Error: Can't resolve './router/index'

ERROR in ./src/index.ts 3:0-36

Module not found: Error: Can't resolve './router/index'

需要在webpack.config.js文件中配置resolve/extensions,默认值['.js', '.json', '.wasm']

resolve: {
        extensions: ['.ts', '.js']
    }
  • 修改src目录下的App.vue文件如下:
<template>
    <nav class="left">
        <router-link to="/css/flex" class="link">CSS flex</router-link>
    </nav>
    <router-view class="right">
        
    </router-view>
    
</template>

<script setup lang="ts">
import { RouterLink, RouterView} from 'vue-router'
   
</script>

使用Scss

  • 安装sass-loader / sass
  • 配置module/rules如下:
 {
                test: /\.s[ac]ss$/i,
                use: [
                    'style-loader',
                    'css-loader',
                    'sass-loader'
                ]
            }

报错: at-rule or selector expectedcss(css-ruleorselectorexpected)

image.png 解决方案:vscode打开设置,把下面的勾选去掉

image.png image.png


网站公告

今日签到

点亮在社区的每一天
去签到