Gói web css mã thông báo không mong đợi

Tôi gặp lỗi "SyntaxError. Mã thông báo không hợp lệ hoặc không mong muốn". Tôi gặp lỗi này ngay cả khi tôi thậm chí không cố gắng sử dụng nó, nó tự hỏng khi nhập

SyntaxError: Invalid or unexpected token
    at wrapSafe (internal/modules/cjs/loader.js:979:16)
    at Module._compile (internal/modules/cjs/loader.js:1027:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)

Tôi muốn hỏi làm thế nào tôi có thể sử dụng nó sau đó, nhưng tôi không biết làm thế nào để nhập nó trước khi tôi có thể thử sử dụng nó

Lưu ý rằng khi hiển thị một phía máy chủ thành phần duy nhất, tôi không muốn chạy lại webpack hoặc bất kỳ thứ gì tương tự, do đó, làm cách nào tôi có thể sử dụng hình ảnh bằng cách nhập mà không cần sử dụng webpack?

Tôi bắt đầu tin rằng cách duy nhất để thực hiện điều này là sử dụng fs. writeFile và đặt thủ công URL tĩnh cho nguồn hình ảnh, nhưng tôi đã hy vọng có một cách tiếp cận tốt hơn;

CHỈNH SỬA. Tôi nghĩ tôi đã tìm ra giải pháp cho vấn đề này nhưng vẫn không gặp may

Bạn có thể có một cái gì đó như thế này, có thể hiển thị một trang

export const component = async (
  request: Request,
  response: Response,
): Promise => {
  console.log(request.url)

  const stream = renderToNodeStream()

  stream.pipe(response)

  stream.on('end', () => {
    response.end()
  })
}

Gần như mọi bài đăng trên blog và ví dụ trên internet đều dừng lại ở đó và nói "được rồi, công việc đã hoàn thành", nhưng không phải vậy, đó thậm chí còn chưa phải là một nửa câu chuyện

Khi bạn sử dụng ở trên cùng với

import Favicon from '/path/to/favicon.ico'

Nó sẽ phá vỡ bên trong thành phần đó vì TypeScript không thể đọc bất kỳ hình ảnh nào, điều này hợp lý. Nó cũng sẽ phá vỡ mọi CSS hoặc các phần tử không phản ứng khác. Điều đó có nghĩa là bạn không thể sử dụng lại bất kỳ thành phần phía máy khách nào và kết xuất lại chúng trên máy chủ nếu chúng chứa bất kỳ hình ảnh, CSS hoặc các thành phần không phải TypeScript/Reac nào khác

Bạn có thể dùng

import webpack from 'webpack'

import config.js from './config'

...

const compiler = webpack(config('production'))

compiler.run((error, stats) => {
  compiler.close()
})

Nó sẽ phá vỡ bên trong thành phần đó vì TypeScript không thể đọc bất kỳ hình ảnh nào, điều này hợp lý. Nó cũng sẽ phá vỡ mọi CSS hoặc các phần tử không phản ứng khác. Điều đó có nghĩa là bạn không thể sử dụng lại bất kỳ thành phần phía máy khách nào và kết xuất lại chúng trên máy chủ nếu chúng chứa bất kỳ hình ảnh, CSS hoặc các thành phần không phải TypeScript/Reac nào khác

Bạn không thể chỉ sử dụng thủ công vì mã máy chủ và mã máy khách của bạn sẽ khác, khiến hydrat bị phàn nàn, vì webpack hiển thị hình ảnh khác với bạn đang thực hiện thủ công. Bạn cũng sẽ không thể sử dụng lại các thành phần tương tự với thứ gì đó như nhập Thành phần từ '. /component' vì bạn sẽ phải sao chép toàn bộ cơ sở mã của mình, một lần cho ứng dụng webpack và một lần để viết đường dẫn hình ảnh theo cách thủ công

Vì vậy, làm cách nào để bạn có thể kết xuất một hình ảnh bằng cách sử dụng renderToString? . Hơn nữa, tại sao mọi người chỉ đơn giản nói, "Ồ, chỉ cần sử dụng renderToString và thì đấy," trong khi rõ ràng là renderToString không hoạt động đối với hình ảnh, CSS hoặc bất kỳ thứ gì khác?

Có mảnh ghép nào tôi đang thiếu hay tôi đang nhìn thấy điều gì đó hiển nhiên?

Điều đầu tiên cần làm nổi bật là việc sử dụng bất kỳ phương thức máy chủ phản ứng nào mà không có một số loại trình đóng gói như webpack là không thể hoặc có thể nhưng vô nghĩa vì bạn sẽ có hình ảnh, CSS và những thứ khác mà bản thảo không thể hiểu được

Điều đầu tiên bạn cần là cấu hình webpack bình thường mà bạn đã quen

const config = {
  output: {
    path: path.join(__dirname, 'public'),
    filename: '[contenthash].js',
    assetModuleFilename: '[contenthash].[ext]',
    publicPath: '/',
    libraryTarget: 'umd',
    clean: false,
  },
  target: 'web',
  resolve: {
    extensions: ['.js', '.ts', '.jsx', '.tsx'],
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: [/node_modules/],
      },
      {
        test: /\.(jpg|png|ico)$/,
        type: 'asset/resource',
        generator: {
          filename: '[contenthash].[ext]',
        },
      },
    ],
  },
  ...

Nó không phải là cấu hình hoàn chỉnh nhưng nó sẽ đưa ra một ý tưởng chung. Ở đó bạn có thể sử dụng tất cả các plugin thông thường và những thứ bạn đã quen, tôi. e. trình tải tệp hoặc trình tải kiểu hoặc bất cứ thứ gì

Sau đó, giả sử rằng bạn có cấu trúc thư mục như thế này

- webpack.config.js
- ui/route // we want all files here to be SSR and client side rendered

Sau đó, bạn có thể gói tất cả những thứ đó như bình thường và phục vụ phía máy khách bằng cách sử dụng thiết lập webpack thông thường của bạn. Tuy nhiên, ngoài ra, bạn sẽ cần một số loại trình biên dịch để viết. js để các chức năng của máy chủ phản ứng sử dụng. Đây là phần quan trọng

import fs from 'fs'
import path from 'path'
import webpack from 'webpack'

import config from '../webpack.config.js'

const configuration = config({production: true})

const files = fs.readdirSync(path.join(__dirname, 'ui/route'))

for (const file of files) {
  if (file.indexOf('.map') === -1) {
    configuration.target = 'node'
    configuration.entry = path.join(__dirname, 'ui/route', file)
    configuration.output.path = path.join(__dirname, '../public')
    configuration.output.filename = file // [contenthash].js

    const compiler = webpack(configuration)
    compiler.run((error) => {
      console.log(error)

      compiler.close((error) => {
        console.log(error)
      })
    })
  }
}

Mã đó khá thô và vẫn có thể được tối ưu hóa theo nhiều cách khác nhau, nhưng nó thể hiện những gì bạn có thể đạt được. Bạn có thể thực hiện từng tệp riêng lẻ hoặc bạn có thể sử dụng một quả cầu để đọc mọi thứ từ một thư mục cụ thể (hoặc tìm kiếm nó theo cách đệ quy), sau đó gọi trình biên dịch gói webpack theo chương trình và xuất riêng từng tệp (trang (tuyến đường)) vào các thư mục của chúng dưới dạng. js, mỗi tệp có CSS/Hình ảnh/bất cứ thứ gì đã được biên dịch bằng webpack của riêng chúng. Một điều cần lưu ý ở đây là bạn không cần phải xây dựng các cấu hình webpack riêng biệt mà không có lý do;

Sau đó, bạn có thể đưa trình biên dịch này vào giai đoạn xây dựng của mình để bạn có thể khởi động máy chủ với thứ gì đó như tsc && node lib/compiler. js && lib/máy chủ. js mọi lúc. Điều này sẽ tạo mọi thứ, sau đó gọi webpack trên mọi thứ và xuất các tệp, sau đó bạn có thể khởi động máy chủ. Bạn cũng có thể làm điều đó một cách linh hoạt nếu bạn chọn. Điều quan trọng ở đây là TypeScript chỉ nên biên dịch các tập lệnh phía máy chủ của bạn, trong khi webpack (sử dụng ts-loader để gọi TypeScript) sẽ biên dịch các tệp giao diện người dùng của bạn