项目代码:Github
新建项目src/index.ts
git initpnpm initpnpm installnpx tsc --init

在 package.json 文件中添加打包脚本:
ts/js打包编译:babel-loader,@babel/core,@babel/preset-env,@babel/preset-typescript
vue打包编译:vue,vue-loader,@vue/compiler-sfc
webpack打包编译:webpack,webpack-cli
自动热更新server:webpack-dev-server
{"name": "webpack-demo","version": "1.0.0","description": "","main": "index.js","scripts": {"build": "rm -rf dist && webpack --config ./config/webpack.prod.js","serve": "webpack serve --config ./config/webpack.dev.js","deploy": "http-server dist -p 8080"},"keywords": [],"author": "","license": "ISC","devDependencies": {"@babel/core": "^7.17.10","@babel/preset-env": "^7.17.10","@babel/preset-typescript": "^7.16.7","@vue/compiler-sfc": "^3.2.33","babel-loader": "^8.2.5","css-loader": "^6.7.1","html-webpack-plugin": "^5.5.0","mini-css-extract-plugin": "^2.6.0","sass": "^1.51.0","sass-loader": "^12.6.0","style-loader": "^3.3.1","typescript": "^4.6.4","vue-loader": "^17.0.0","webpack": "^5.72.0","webpack-cli": "^4.9.2","webpack-dev-server": "^4.9.0","webpack-merge": "^5.8.0"},"dependencies": {"http-server": "^14.1.0","vue": "^3.2.33"}}
识别声明 vue 文件,babel插件配置。.vue 文件的解析还需要 @vue/compoiler-sfc 这个包。
declare module "*.vue" {import type { DefineComponent } from "vue";const component: DefineComponent<{}, {}, any>;export default component;}
module.exports = {presets: ["@babel/preset-env",["@babel/preset-typescript",{allExtensions: true, //支持所有文件扩展名},],],};
```json { “compilerOptions”: { / Visit https://aka.ms/tsconfig.json to read more about this file /
/ Projects / // “incremental”: true, / Enable incremental compilation / // “composite”: true, / Enable constraints that allow a TypeScript project to be used with project references. / // “tsBuildInfoFile”: “./“, / Specify the folder for .tsbuildinfo incremental compilation files. / // “disableSourceOfProjectReferenceRedirect”: true, / Disable preferring source files instead of declaration files when referencing composite projects / // “disableSolutionSearching”: true, / Opt a project out of multi-project reference checking when editing. / // “disableReferencedProjectLoad”: true, / Reduce the number of projects loaded automatically by TypeScript. /
/ Language and Environment / “target”: “es2016”, / Set the JavaScript language version for emitted JavaScript and include compatible library declarations. / “lib”: [“ESNext”,”DOM”], / Specify a set of bundled library declaration files that describe the target runtime environment. / “jsx”: “preserve”, / Specify what JSX code is generated. / // “experimentalDecorators”: true, / Enable experimental support for TC39 stage 2 draft decorators. / // “emitDecoratorMetadata”: true, / Emit design-type metadata for decorated declarations in source files. / // “jsxFactory”: “”, / Specify the JSX factory function used when targeting React JSX emit, e.g. ‘React.createElement’ or ‘h’ / // “jsxFragmentFactory”: “”, / Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. ‘React.Fragment’ or ‘Fragment’. / // “jsxImportSource”: “”, / Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx
./ // “reactNamespace”: “”, / Specify the object invoked forcreateElement. This only applies when targetingreactJSX emit. / // “noLib”: true, / Disable including any library files, including the default lib.d.ts. / // “useDefineForClassFields”: true, / Emit ECMAScript-standard-compliant class fields. *// Modules / “module”: “ESNext”, / Specify what module code is generated. / // “rootDir”: “./“, / Specify the root folder within your source files. / “moduleResolution”: “node”, / Specify how TypeScript looks up a file from a given module specifier. / “baseUrl”: “.”, / Specify the base directory to resolve non-relative module names. / “paths”: { “@/“: [“src/“], }, / Specify a set of entries that re-map imports to additional lookup locations. / // “rootDirs”: [], / Allow multiple folders to be treated as one when resolving modules. / // “typeRoots”: [], / Specify multiple folders that act like
./node_modules/@types. / // “types”: [], / Specify type package names to be included without being referenced in a source file. / // “allowUmdGlobalAccess”: true, / Allow accessing UMD globals from modules. / // “resolveJsonModule”: true, / Enable importing .json files / // “noResolve”: true, / Disallowimports,requires or<reference>s from expanding the number of files TypeScript should add to a project. // JavaScript Support / // “allowJs”: true, / Allow JavaScript files to be a part of your program. Use the
checkJSoption to get errors from these files. / // “checkJs”: true, / Enable error reporting in type-checked JavaScript files. / // “maxNodeModuleJsDepth”: 1, / Specify the maximum folder depth used for checking JavaScript files fromnode_modules. Only applicable withallowJs. // Emit / // “declaration”: true, / Generate .d.ts files from TypeScript and JavaScript files in your project. / // “declarationMap”: true, / Create sourcemaps for d.ts files. / // “emitDeclarationOnly”: true, / Only output d.ts files and not JavaScript files. / // “sourceMap”: true, / Create source map files for emitted JavaScript files. / // “outFile”: “./“, / Specify a file that bundles all outputs into one JavaScript file. If
declarationis true, also designates a file that bundles all .d.ts output. / // “outDir”: “./“, / Specify an output folder for all emitted files. / // “removeComments”: true, / Disable emitting comments. / // “noEmit”: true, / Disable emitting files from a compilation. / // “importHelpers”: true, / Allow importing helper functions from tslib once per project, instead of including them per-file. / // “importsNotUsedAsValues”: “remove”, / Specify emit/checking behavior for imports that are only used for types / // “downlevelIteration”: true, / Emit more compliant, but verbose and less performant JavaScript for iteration. / // “sourceRoot”: “”, / Specify the root path for debuggers to find the reference source code. / // “mapRoot”: “”, / Specify the location where debugger should locate map files instead of generated locations. / // “inlineSourceMap”: true, / Include sourcemap files inside the emitted JavaScript. / // “inlineSources”: true, / Include source code in the sourcemaps inside the emitted JavaScript. / // “emitBOM”: true, / Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. / // “newLine”: “crlf”, / Set the newline character for emitting files. / // “stripInternal”: true, / Disable emitting declarations that have@internalin their JSDoc comments. / // “noEmitHelpers”: true, / Disable generating custom helper functions like__extendsin compiled output. / // “noEmitOnError”: true, / Disable emitting files if any type checking errors are reported. / // “preserveConstEnums”: true, / Disable erasingconst enumdeclarations in generated code. / // “declarationDir”: “./“, / Specify the output directory for generated declaration files. / // “preserveValueImports”: true, / Preserve unused imported values in the JavaScript output that would otherwise be removed. // Interop Constraints / // “isolatedModules”: true, / Ensure that each file can be safely transpiled without relying on other imports. / // “allowSyntheticDefaultImports”: true, / Allow ‘import x from y’ when a module doesn’t have a default export. / “esModuleInterop”: true, / Emit additional JavaScript to ease support for importing CommonJS modules. This enables
allowSyntheticDefaultImportsfor type compatibility. / // “preserveSymlinks”: true, / Disable resolving symlinks to their realpath. This correlates to the same flag in node. / “forceConsistentCasingInFileNames”: true, / Ensure that casing is correct in imports. // Type Checking / “strict”: false, / Enable all strict type-checking options. / // “noImplicitAny”: true, / Enable error reporting for expressions and declarations with an implied
anytype.. / // “strictNullChecks”: true, / When type checking, take into accountnullandundefined. / // “strictFunctionTypes”: true, / When assigning functions, check to ensure parameters and the return values are subtype-compatible. / // “strictBindCallApply”: true, / Check that the arguments forbind,call, andapplymethods match the original function. / // “strictPropertyInitialization”: true, / Check for class properties that are declared but not set in the constructor. / // “noImplicitThis”: true, / Enable error reporting whenthisis given the typeany. / // “useUnknownInCatchVariables”: true, / Type catch clause variables as ‘unknown’ instead of ‘any’. / // “alwaysStrict”: true, / Ensure ‘use strict’ is always emitted. / // “noUnusedLocals”: true, / Enable error reporting when a local variables aren’t read. / // “noUnusedParameters”: true, / Raise an error when a function parameter isn’t read / // “exactOptionalPropertyTypes”: true, / Interpret optional property types as written, rather than adding ‘undefined’. / // “noImplicitReturns”: true, / Enable error reporting for codepaths that do not explicitly return in a function. / // “noFallthroughCasesInSwitch”: true, / Enable error reporting for fallthrough cases in switch statements. / // “noUncheckedIndexedAccess”: true, / Include ‘undefined’ in index signature results / // “noImplicitOverride”: true, / Ensure overriding members in derived classes are marked with an override modifier. / // “noPropertyAccessFromIndexSignature”: true, / Enforces using indexed accessors for keys declared using an indexed type / // “allowUnusedLabels”: true, / Disable error reporting for unused labels. / // “allowUnreachableCode”: true, / Disable error reporting for unreachable code. // Completeness / // “skipDefaultLibCheck”: true, / Skip type checking .d.ts files that are included with TypeScript. / “skipLibCheck”: true / Skip type checking all .d.ts files. / } }
4. 配置文件拆分webpack.config.js 可以按照工程化思维拆分成 webpack.base.js、webpack.dev.js、webpack.prod.js 三个文件,基本配置放在 base 文件,用 webpack-merge 合并到 dev/prod 文件。```javascriptconst HtmlWebpackPlugin = require('html-webpack-plugin')const { VueLoaderPlugin } = require("vue-loader");const { DefinePlugin } = require('webpack');const path = require("path");const MiniCssExtractPlugin = require("mini-css-extract-plugin");const devMode = process.env.NODE_ENV !== "production";module.exports = {// 入口文件entry: './src/index.ts',// 打包输出output: {filename: 'main.[contenthash].js',path: path.resolve(__dirname, '../dist'),/** chunkFilename用来打包require.ensure方法中引入的模块,如果该方法中没有引入任何模块则不会生成任何chunk块文件* 比如在main.js文件中,require.ensure([],function(require){alert(11);}),这样不会打包块文件* 只有这样才会打包生成块文件require.ensure([],function(require){alert(11);require('./greeter')})* 或者这样require.ensure(['./greeter'],function(require){alert(11);})* chunk的hash值只有在require.ensure中引入的模块发生变化,hash值才会改变* 注意:对于不是在ensure方法中引入的模块,此属性不会生效,只能用CommonsChunkPlugin插件来提取**/chunkFilename:'[chunkhash:8].chunk.js'},plugins: [// 配置html模板插件new HtmlWebpackPlugin({title: 'Webpack demo',template: './src/assets/index.html',}),new VueLoaderPlugin(),new DefinePlugin({BASE_URL: "'./'",__VUE_OPTIONS_API__: true, // 这里必须是布尔值,不能写成字符串__VUE_PROD_DEVTOOLS__: false // 这里必须是布尔值,不能写成字符串}),],resolve:{// 设置路径别名alias: {'@': path.resolve(__dirname, '../src'),},// 省略拓展名,虽然会带来一些便利,但实际上会在一定程度上影响 webpack 的运行效率,不推荐修改extensions: ['.ts', '.js', '.json']},module: {rules: [// 将 ts/js 用 babel 编译成 es5{test: /\.(t|j)s$/,exclude: /node_modules/,use: {loader: "babel-loader",options: {cacheDirectory: true,},},},{test: /\.vue$/,use: "vue-loader",},// dev环境用style-loader,prod环境用miniCss{test: /\.(sa|sc|c)ss$/,use: [devMode ? "style-loader" : MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],},// 图片类型打包{test: /\.(png|svg|jpe?g|gif)$/,type: "asset",generator: {filename: "images/[name]-[hash][ext]",},},// 字体类型打包{test: /\.(eot|svg|ttf|woff2?|)$/,type: "asset/resource",generator: {filename: "fonts/[name]-[hash][ext]",},},],},};
const { merge } = require("webpack-merge");const baseConfig = require("./webpack.base.js");module.exports = merge(baseConfig, {mode: 'development',// webpack升级到5.0后,target默认值值会根据package.json中的browserslist改变,导致devServer的自动更新失效// 所以 development 环境下直接配置成 webtarget: "web",devServer: {hot: true, // 启用热模块替换open: true, // 打开默认浏览器proxy: {"/api": {// 需要代理到的真实目标服务器,如/api/user会被代理到https://www.juejin.cn/api/usertarget: "https://www.juejin.cn",// 是否更改代理后请求的headers中host地址,某些安全级别较高的服务器会对此做校验changeOrigin: true,// 默认情况下不接受将请求转发到https的api服务器上,如果希望支持,可以设置为falsesecure: false,// 默认情况下/api也会写入到请求url中,通过这个配置可以将其删除pathRewrite: {"^/api": "/",},},}},})
const { merge } = require("webpack-merge");const baseConfig = require("./webpack.base.js");const MiniCssExtractPlugin = require("mini-css-extract-plugin");module.exports = merge(baseConfig, {mode: "production",// 代码分隔optimization: {splitChunks: {// 选择对哪些文件进行拆分,默认是async,即只对动态导入的文件进行拆分chunks: "all",// 提取chunk的最小体积minSize: 20000,// 要提取的chunk最少被引用次数minChunks: 1,// 对要提取的trunk进行分组,根据业务逻辑去拆包cacheGroups: {// 匹配node_modules中的三方库,将其打包成一个trunkdefaultVendors: {test: /[\\/]node_modules[\\/]/,name: "vendors",priority: -10,},default: {// 将至少被两个trunk引入的模块提取出来打包成单独trunkminChunks: 2,name: "default",priority: -20,},},},},// 抽离出css成一个单独文件,生产环境用,这样在浏览器中可以拥有更好的加载效率plugins: [new MiniCssExtractPlugin()],});
- index.html/main.ts/App.vue文件
```typescript import { createApp } from “vue”; import App from “@/App.vue”; import ‘@/style.css’<!DOCTYPE html><html lang="zh"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover"><title><%= htmlWebpackPlugin.options.title %></title></head><body><div id="app"></div></body></html>
createApp(App).mount(“#app”);
```vue<template><div class="app"><h1 class="example">{{ name }}</h1><img src="../static/nature.jpg" alt="backImg"></div></template><script lang="ts">import { defineComponent } from "vue";export default defineComponent({setup() {const name = "Hello Webpack5 Vue3";return {name,};},});</script><style scoped lang="scss">.app{.example{color: blue;}img{height: 200px;width: 200px;}}</style>
