gravity-ui / uikit

https://gravity-ui.com
MIT License
555 stars 87 forks source link

SyntaxError: Unexpected token '.' #1487

Closed v0vchansky closed 2 months ago

v0vchansky commented 5 months ago

Привет, пытаюсь затащить библиотеку с UI в проект с SSR, но при старте приложения получаю ошибку:

start:server] /Users/v0vchansky/Desktop/Projects/roomtodo/roomtodo/node_modules/@gravity-ui/uikit/build/cjs/components/Icon/Icon.css:1
[start:server] .g-icon {
[start:server] ^
[start:server] 
[start:server] SyntaxError: Unexpected token '.'
[start:server]     at internalCompileFunction (node:internal/vm:77:18)
[start:server]     at wrapSafe (node:internal/modules/cjs/loader:1288:20)
[start:server]     at Module._compile (node:internal/modules/cjs/loader:1340:27)
[start:server]     at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
[start:server]     at Module.load (node:internal/modules/cjs/loader:1207:32)
[start:server]     at Module._load (node:internal/modules/cjs/loader:1023:12)
[start:server]     at Module.require (node:internal/modules/cjs/loader:1235:19)
[start:server]     at require (node:internal/modules/helpers:176:18)
[start:server]     at Object.<anonymous> (/Users/v0vchansky/Desktop/Projects/roomtodo/roomtodo/node_modules/@gravity-ui/uikit/build/cjs/components/Icon/Icon.js:9:1)
[start:server]     at Module._compile (node:internal/modules/cjs/loader:1376:14)
[start:server] 
[start:server] Node.js v21.2.0
ERROR: "start:server" exited with 1.

webpack.config.ts:

import path from 'path';
import { Configuration } from 'webpack';
import TerserPlugin from 'terser-webpack-plugin';
import LoadablePlugin from '@loadable/webpack-plugin';
import nodeExternals from 'webpack-node-externals';
import { TsconfigPathsPlugin } from 'tsconfig-paths-webpack-plugin';
import FileManagerPlugin from 'filemanager-webpack-plugin';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';

const fileRegex = /^(?!.*\.inline).*\.(svg|jpe?g|png|gif|eot|woff2?|ttf)$/;

const IS_DEV = process.env.NODE_ENV !== 'production';

const outputPath = path.resolve(__dirname, 'dist/');

const client = {
    entry: {
        main: path.resolve(__dirname, './src/index.tsx'),
    },
    // entry: path.resolve('./src/index.tsx'),
    mode: IS_DEV ? 'development' : 'production',
    devtool: 'source-map',
    target: 'web',
    output: {
        // filename: 'main.js',
        chunkFilename: '[name].[chunkhash].js',
        path: outputPath,
    },
    plugins: [
        new LoadablePlugin(),
        new MiniCssExtractPlugin(),
        // new FileManagerPlugin({
        //  events: {
        //      onStart: {
        //          delete: ['dist'],
        //      },
        //  },
        // }),
    ],
    resolve: {
        extensions: ['.js', '.ts', '.jsx', '.tsx'],
        alias: {
            '@app': path.resolve(__dirname, 'src/client'),
        },
    },
    optimization: {
        minimize: false, // <---- disables uglify.
        minimizer: [
            new TerserPlugin({
                test: /\.js(\?.*)?$/i,
                terserOptions: {
                    compress: {
                        drop_console: false,
                    },
                },
            }),
        ],
        // minimizer: [new UglifyJsPlugin()] if you want to customize it.
    },
    module: {
        rules: [
            {
                test: /\.(ts|tsx|js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    // options: {
                    //  presets: [
                    //      '@babel/preset-env',
                    //      '@babel/preset-react',
                    //      '@babel/preset-typescript',
                    //  ],
                    //  plugins: ['@loadable/babel-plugin'],
                    // },
                },
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: 'style-loader',
                    },
                    {
                        loader: 'css-loader',
                    },
                    {
                        loader: 'postcss-loader',
                    },
                    {
                        loader: 'sass-loader',
                    },
                ],
            },
            // {
            //  test: /\.css$/,
            //  use: ['style-loader', 'css-loader'],
            // },
            {
                test: /\.(png|jpg|jpeg|svg|ttf)$/i,
                type: 'asset/resource',
            },
        ],
    },
};

const server: Configuration = {
    name: 'server',
    target: 'node',
    node: { __dirname: false },
    entry: path.relative(__dirname, './src/server/index.tsx'),
    output: {
        filename: 'server.js',
        libraryTarget: 'commonjs2',
        path: outputPath,
        publicPath: '/static/',
    },
    resolve: {
        // modules: ['src'],
        extensions: ['.js', '.jsx', '.ts', '.tsx'],
        plugins: [new TsconfigPathsPlugin({ configFile: './tsconfig.json' })],
    },
    // plugins: [new MiniCssExtractPlugin()],

    devtool: 'source-map',

    // performance: {
    //  hints: IS_DEV ? false : 'warning',
    // },

    externals: [nodeExternals({ allowlist: [/\.(?!(?:tsx?|json)$).{1,5}$/i] })],

    // optimization: { nodeEnv: false },

    module: {
        rules: [
            {
                test: /\.(js|jsx|ts|tsx)$/,
                exclude: /node_modules/,
                use: { loader: 'babel-loader' },
            },
            {
                test: /\.css$/,
                loader: 'null-loader',
                // use: [
                //  {
                //      loader: 'style-loader',
                //  },
                //  {
                //      loader: 'css-loader',
                //  },
                //  {
                //      loader: 'postcss-loader',
                //  },
                //  {
                //      loader: 'sass-loader',
                //  },
                // ],
            },
            {
                loader: 'null-loader',
                test: fileRegex,
            },
        ],
    },
};

module.exports = [client, server];

package.json:

...
"scripts": {
  "build": "webpack --config webpack.config.ts",
  "start:client": "webpack --mode=development --watch",
  "start:server": "node dist/server.js",
  "start": "npm run build && NODE_ENV=development npm-run-all --print-label --parallel start:*"
},
...

С другими UI библиотеками такого не происходит(

Заранее спасибо за помощь <3

ValeraS commented 5 months ago

Try to add @gravity-ui/uikit to a nodeExternals allow list:

externals: [nodeExternals({allowlist: ['@gravity-ui/uikit']})],

/\.(?!(?:tsx?|json)$).{1,5}$/i - this works only for files explicitly imported in your project, for example import @gravity-ui/uikit/styles/styles.scss;`

v0vchansky commented 5 months ago

@ValeraS I LOVE YOU ❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️

saxumcordis commented 5 months ago

Whats fix for app-builder? doesnt work(

image

@ValeraS

ValeraS commented 5 months ago

@saxumcordis app-builder does not support ssr and so does not use webpack to compile server code. What do you use from @gravity-ui/uikit on server in your project?

saxumcordis commented 5 months ago

@ValeraS import type {RealTheme} from '@gravity-ui/uikit/build/esm/components/theme/types'; this import only.. maybe somthing in other imports from other pkgs.. will check it