【问题标题】:Integration of back-end webpack with Vue-CLI 3后端 webpack 与 Vue-CLI 3 的集成
【发布时间】:2019-07-24 17:00:11
【问题描述】:

我正在使用 Vue-CLI 3 开发一个全栈应用程序。后端是用 TypeScript 编写的,因此需要编译等。目前我只是使用 ts-node 直接运行后端应用程序,它可以工作,但它如果我还可以 webpack 后端应用程序以提供单个 server.js 而不是遍布整个地方的多个庞大的打字稿文件,那将会更干净。

问题是我通常这样做的方式是有一个webpack.base.js,然后将其包含在不同的 webpack 配置文件中。我真的不能这样做,因为很多 webpack 配置都隐藏在 vue-cli-service

【问题讨论】:

    标签: vue.js


    【解决方案1】:

    最终有了一个基本的 webpack 配置并扩展了客户端和服务器 webpack 配置。

    我的应用根webpack.config.js 如下所示:

    const { config: client } = require('./src/client/webpack.config');
    const { config: server } = require('./src/server/webpack.config');
    
    /**
     * Webpack Build File
     *
     * This webpack configuration is used for only building the client and server
     * bundles. It imports both of these from their respective directories, but
     * allows for overrides if required.
     *
     * Other dev tools such as watching, hot module reloading etc. has been split
     * out into other config files
     *
     * @param {object} env Webpack `env` object
     */
    module.exports = ({ mode = 'development' } = {}) => ([
      {
        ...client({ mode }, process.env),
      },
      {
        ...server({ mode }, process.env),
      },
    ]);
    

    我的src/client/webpack.config.js 看起来像这样:

    const { resolve: _resolve, sep } = require('path');
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    const TSConfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const HtmlWebpackRootElementPlugin = require('html-webpack-root-plugin');
    const VueLoaderPlugin = require('vue-loader/lib/plugin');
    const { DefinePlugin } = require('webpack');
    
    const paths = {
      src: {
        rootDir: _resolve(__dirname) + sep,
        app: _resolve(__dirname, 'app') + sep,
      },
      dist: {
        rootDir: _resolve(__dirname, '..', '..', 'dist'),
        app: _resolve(__dirname, '..', '..', 'dist', 'public'),
      },
    };
    
    /**
     * Client webpack build configuration.
     *
     * This webpack config produces a bundle for the client-side application only.
     *
     * @param {object} webpackEnv Webpack env object (basically any/all options passed in via the CLI)
     * @param {object} processEnv Process env object (environment variables from process.env)
     */
    const config = ({ mode = 'none' }, { APP_NAME = '', BASE_URL = '/' } = {}) => ({
      name: 'client',
      target: 'web',
      mode,
      entry: {
        app: paths.src.app + 'main.ts',
      },
      output: {
        path: paths.dist.app,
      },
      optimization: {
        runtimeChunk: 'single',
      },
      resolve: {
        extensions: ['.ts', '.js', '.vue'],
        plugins: [
          new TSConfigPathsPlugin({
            configFile: paths.src.rootDir + 'tsconfig.json',
          }),
        ],
      },
      context: paths.src.rootDir,
      module: {
        rules: [
          {
            test: /\.tsx?$/,
            include: paths.src.rootDir,
            exclude: /node_modules/,
            use: [
              {
                loader: 'ts-loader',
                options: {
                  happyPackMode: true,
                },
              },
            ],
          },
          {
            test: /\.vue$/,
            loader: 'vue-loader',
          },
          {
            test: /\.js$/,
            exclude: /node_modules/,
            use: {
              loader: 'babel-loader',
            },
          },
          {
            test: /\.s?[ac]ss$/,
            use: [
              'style-loader',
              'css-loader',
              'sass-loader',
            ],
          },
          {
            test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i,
            loader: 'file-loader',
            options: {
              name: 'assets/[name].[hash].[ext]',
              esModule: false,
            },
          },
        ],
      },
      plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
          favicon: paths.src.app + 'assets/logo.png',
          title: APP_NAME,
        }),
        new HtmlWebpackRootElementPlugin('app'),
        new VueLoaderPlugin(),
        new DefinePlugin({
          'process.env.BASE_URL': JSON.stringify(BASE_URL),
        }),
      ],
    });
    
    module.exports = {
      config,
      paths,
    };
    

    而我的src/server/webpack.config.js 看起来像这样:

    const { resolve: _resolve, sep } = require('path');
    const TSConfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
    const nodeExternals = require('webpack-node-externals');
    const { IgnorePlugin } = require('webpack');
    
    const paths = {
      src: _resolve(__dirname) + sep,
      dist: _resolve(__dirname, '..', '..', 'dist'),
    };
    
    /**
     * NestJs uses a custom wrapper around require() that allows it to show a
     * warning when some extra package needs to be installed. This causes problems
     * with webpack, so we're blacklisting packages we're not using with the
     * IgnorePlugin below.
     *
     * To de-blacklist a package, just remove it from this array.
     */
    const nestBlacklist = [
      '^cache-manager$',
      '^@nestjs/microservices$',
      // packages below are required from microservices
      '^amqp-connection-manager$',
      '^amqplib$',
      '^grpc$',
      '^mqtt$',
      '^nats$',
      '^redis$',
    ];
    
    /**
     * Server webpack build configuration.
     *
     * This webpack config produces a bundle for the server-side application only.
     *
     * @param {object} webpackEnv Webpack env object (basically any/all options passed in via the CLI)
     * @param {object} processEnv Process env object (environment variables from process.env)
     */
    const config = ({ mode = 'none' }) => ({
      name: 'server',
      mode,
      target: 'node',
      entry: paths.src + 'main.ts',
      externals: [nodeExternals()],
      output: {
        path: paths.dist,
        filename: 'server.js',
      },
      resolve: {
        extensions: ['.ts', '.js'],
        plugins: [
          new TSConfigPathsPlugin({
            configFile: './tsconfig.build.json',
          }),
        ],
      },
      context: paths.src,
      optimization: {
        minimize: false,
      },
      module: {
        rules: [
          {
            test: /\.js$/,
            exclude: /node_modules/,
            use: {
              loader: 'babel-loader',
            },
          },
          {
            test: /\.ts$/,
            include: paths.src,
            exclude: /node_modules/,
            use: [
              {
                loader: 'ts-loader',
                options: {
                  happyPackMode: true,
                },
              },
            ],
          },
        ],
      },
      plugins: [
        new IgnorePlugin({
          contextRegExp: /@nestjs/,
          resourceRegExp: new RegExp(nestBlacklist.join('|')),
        }),
      ],
      node: {
        __dirname: false,
      },
    });
    
    module.exports = {
      config,
      paths,
    };
    

    这使我可以拥有不同的服务器端和客户端编译配置,但可以在其他配置中重复使用。因此,对于 webpack 开发服务器 - 我有 webpack.dev.config.js,其中包含以下内容:

    const client = require('./src/client/webpack.config');
    const server = require('./src/server/webpack.config');
    const { HotModuleReplacementPlugin } = require('webpack');
    
    const {
      SERVER_PORT = 3000,
    } = process.env;
    
    /**
     * Watch settings are the same between client and server, so we're keeping them
     * here for consistency
     */
    const watchConfig = {
      watch: true,
      watchOptions: {
        ignored: /node_modules/,
      },
    };
    
    /**
    * Development Webpack Build File
    *
    * This webpack configuration extends `webpack.config.js` and builds on it to
    * provide hot module replacement, watch moide and a dev server for the
    * client-side code
    *
    * Other dev tools such as watching, hot module reloading etc. has been split
    * out into other config files
    *
    * @param {object} env Webpack `env` object
    */
    module.exports = ({ mode = 'development' } = {}) => ([
      {
        ...client.config({ mode }, process.env),
        ...watchConfig,
        devServer: {
          contentBase: client.paths.dist.app,
          historyApiFallback: {
            rewrites: [
              { from: /./, to: '/index.html' },
            ],
          },
          port: 8000,
          host: '0.0.0.0',
          hot: true,
          hotOnly: true,
          proxy: {
            '/api': `http://localhost:${SERVER_PORT}/`,
          },
        },
      },
      {
        ...server.config({ mode }, process.env),
        ...watchConfig,
        plugins: [
          ...server.config({ mode }, process.env).plugins,
          new HotModuleReplacementPlugin(),
        ],
      },
    ]);
    

    此配置提供了一个生成 server.js 的设置,然后提供一个目录(在本例中为“/public”`),因为它是静态文件目录。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-23
      • 2018-09-12
      • 2019-07-02
      • 2022-11-21
      • 2019-03-29
      • 2020-06-14
      • 2023-03-15
      • 2022-10-24
      相关资源
      最近更新 更多